<?php
/**
 * ASISMA CRM - API Pública de Captación de Leads
 *
 * POST /api/leads
 *   Auth: header X-API-KEY o campo api_key. Cada franquiciado tiene su propia
 *   llave (empresas_franquiciados.api_key_leads, visible en su página de
 *   documentación); también sirve la llave global API_KEY_LEADS (config_sistema).
 *   Acepta JSON (Content-Type: application/json) o application/x-www-form-urlencoded.
 *
 *   Campos (todos obligatorios salvo giro/notas/origen):
 *     rut_empresa*     string   RUT de la empresa (validado, crea/reusa ficha)
 *     razon_social*    string   Razón social de la empresa
 *     nombre_empresa*  string   Nombre de fantasía / comercial
 *     nombre_contacto* string   Nombre de la persona de contacto
 *     telefono*        string   Teléfono/WhatsApp
 *     correo*          string   Email del contacto
 *     marca_id         int      FORMA POR DEFECTO: marca de interés — define la
 *                               vertical y hace rotar el lead SOLO entre los
 *                               franquiciados con la marca COMPLETA autorizada
 *     producto_id      int      Alternativa: producto específico — rota entre
 *                               quienes venden ESE producto (marca completa o
 *                               producto suelto). Obligatoria para landings de
 *                               franquiciados que solo venden productos sueltos.
 *                               (Debe venir marca_id O producto_id; si vienen los
 *                               dos, el producto manda y debe calzar con la marca.)
 *     region_id*       int      Región del lead (tabla regiones)
 *     giro             string   Giro comercial
 *     origen           string   web|meta|whatsapp_directo|api|referido (default: api)
 *     notas            string   Nota inicial
 *
 *   Respuesta: { success, lead_id, asignado, duplicado?, message }
 */
class ApiController extends Controller {

    public function capturarLead() {
        $db = Database::getInstance();

        $datos = $this->leerPayload();

        // ── Autenticación por API key (por franquiciado, o la global) ────────
        $apiKeyRecibida = '';
        if (isset($_SERVER['HTTP_X_API_KEY'])) {
            $apiKeyRecibida = trim($_SERVER['HTTP_X_API_KEY']);
        } elseif (isset($datos['api_key'])) {
            $apiKeyRecibida = trim($datos['api_key']);
        }
        if ($apiKeyRecibida === '') {
            $this->logApi('AUTH_FAIL', $datos);
            $this->json(array('success' => false, 'message' => 'Falta la API key (header X-API-KEY o campo api_key).'), 401);
        }

        $franquiciaOrigen = $db->fetchOne(
            "SELECT ef.id, ef.nombre_fantasia
             FROM empresas_franquiciados ef
             WHERE ef.api_key_leads = :llave AND ef.activa = 1 LIMIT 1",
            array('llave' => $apiKeyRecibida)
        );
        if (!$franquiciaOrigen) {
            $apiKeyConfig = $db->fetchOne("SELECT valor FROM config_sistema WHERE clave = 'API_KEY_LEADS' LIMIT 1");
            $llaveGlobal = $apiKeyConfig ? (string)$apiKeyConfig['valor'] : '';
            if ($llaveGlobal === '' || !hash_equals($llaveGlobal, $apiKeyRecibida)) {
                $this->logApi('AUTH_FAIL', $datos);
                $this->json(array('success' => false, 'message' => 'API key inválida.'), 401);
            }
        }

        // ── Validación ───────────────────────────────────────────────────────
        $nombre        = isset($datos['nombre_contacto']) ? trim($datos['nombre_contacto']) : (isset($datos['nombre']) ? trim($datos['nombre']) : '');
        $telefono      = isset($datos['telefono']) ? normalizar_telefono(trim($datos['telefono'])) : '';
        $correo        = isset($datos['correo']) ? trim($datos['correo']) : '';
        $regionId      = isset($datos['region_id']) ? (int)$datos['region_id'] : 0;
        $productoId    = isset($datos['producto_id']) ? (int)$datos['producto_id'] : 0;
        $marcaIdIn     = isset($datos['marca_id']) ? (int)$datos['marca_id'] : 0;
        $rut           = isset($datos['rut_empresa']) ? trim($datos['rut_empresa']) : (isset($datos['rut']) ? trim($datos['rut']) : '');
        $razon         = isset($datos['razon_social']) ? trim($datos['razon_social']) : '';
        $nombreEmpresa = isset($datos['nombre_empresa']) ? trim($datos['nombre_empresa']) : '';
        $giro          = isset($datos['giro']) ? trim($datos['giro']) : '';
        $origen        = isset($datos['origen']) ? trim($datos['origen']) : 'api';
        $notas         = isset($datos['notas']) ? trim($datos['notas']) : '';

        $errores = array();
        if ($rut === '') {
            $errores[] = 'rut_empresa es obligatorio.';
        } elseif (!validar_rut($rut)) {
            $errores[] = 'rut_empresa no es válido (dígito verificador incorrecto).';
        }
        if ($razon === '')         $errores[] = 'razon_social es obligatoria.';
        if ($nombreEmpresa === '') $errores[] = 'nombre_empresa es obligatorio.';
        if ($nombre === '')        $errores[] = 'nombre_contacto es obligatorio.';
        if ($telefono === '')      $errores[] = 'telefono es obligatorio.';
        if ($correo === '') {
            $errores[] = 'correo es obligatorio.';
        } elseif (!filter_var($correo, FILTER_VALIDATE_EMAIL)) {
            $errores[] = 'correo no es un email válido.';
        }
        if ($marcaIdIn <= 0 && $productoId <= 0) {
            $errores[] = 'Debe venir marca_id (forma por defecto) o producto_id (landing de un producto específico) — definen la rotación del lead.';
        }
        if ($regionId <= 0)   $errores[] = 'region_id es obligatorio.';
        if (!array_key_exists($origen, arr_origenes_lead())) {
            $origen = 'api';
        }

        // La vertical se deriva del producto o, en su defecto, de la marca.
        // Lead con producto → rota entre quienes venden ESE producto.
        // Lead solo con marca → rota SOLO entre franquiciados con la marca completa.
        $verticalId = 0;
        $marcaId    = 0;
        if (empty($errores)) {
            $region = $db->fetchOne("SELECT id FROM regiones WHERE id = :id AND activa = 1", array('id' => $regionId));
            if (!$region) $errores[] = 'region_id no existe o está inactiva.';

            if ($productoId > 0) {
                $prod = $db->fetchOne("SELECT id, marca_id, vertical_id FROM productos WHERE id = :id AND activo = 1", array('id' => $productoId));
                if (!$prod) {
                    $errores[] = 'producto_id no existe o está inactivo.';
                } elseif ($marcaIdIn > 0 && $marcaIdIn !== (int)$prod['marca_id']) {
                    $errores[] = 'marca_id no corresponde a la marca del producto_id enviado (si vienen los dos, deben calzar).';
                } else {
                    $verticalId = (int)$prod['vertical_id'];
                    $marcaId    = (int)$prod['marca_id'];
                }
            } else {
                $marca = $db->fetchOne("SELECT id, vertical_id FROM marcas WHERE id = :id AND activa = 1", array('id' => $marcaIdIn));
                if (!$marca) {
                    $errores[] = 'marca_id no existe o está inactiva.';
                } else {
                    $verticalId = (int)$marca['vertical_id'];
                    $marcaId    = (int)$marca['id'];
                }
            }
        }

        if (!empty($errores)) {
            $this->json(array('success' => false, 'message' => 'Datos inválidos.', 'errores' => $errores), 422);
        }

        $rut = normalizar_rut($rut);

        // ── Candado DEFINITIVO anti-duplicado (regla 20-07-2026): mismo telefono
        // en la misma region + vertical + producto (o marca si el lead viene
        // generico) = ese lead ya esta siendo atendido. No se crea duplicado.
        // En otra region el mismo cliente SI puede repetirse (cada region es su mercado).
        $duplicado = CandadoLeadsHelper::leadAtendido(
            $regionId, $verticalId, $marcaId, $productoId > 0 ? $productoId : null, $telefono, null
        );
        if ($duplicado) {
            // TODO (modulo 14 Notificaciones): cuando el mismo lead entra 2 veces
            // por la API hay que ALERTAR A LA MATRIZ — el lead estaba asignado y
            // puede estar quedando tirado. Por ahora solo queda registrado aca.
            $db->insert('actividades_crm', array(
                'lead_id'    => $duplicado['id'],
                'usuario_id' => null,
                'tipo'       => 'sistema',
                'direccion'  => 'interna',
                'asunto'     => 'Reingreso por API — lead posiblemente tirado',
                'detalles'   => 'Este lead volvió a entrar por la API de captación (origen: ' . $origen . ') estando ya atendido en la misma región/segmento. No se creó duplicado. PENDIENTE: alertar a la empresa matriz (módulo Notificaciones).'
            ));
            $this->logApi('LEAD_DUPLICADO', array('lead_id' => (int)$duplicado['id'], 'telefono' => $telefono));
            $this->json(array(
                'success'   => true,
                'duplicado' => true,
                'lead_id'   => (int)$duplicado['id'],
                'message'   => 'Este lead ya está siendo atendido en esa región y segmento. Se registró el reingreso.'
            ));
        }

        // ── Candado por empresa: lead abierto en la misma región y vertical ──
        $empresaExistente = $db->fetchOne("SELECT id FROM empresas WHERE rut = :rut", array('rut' => $rut));
        if ($empresaExistente) {
            $leadEmpresa = $db->fetchOne(
                "SELECT id FROM leads
                 WHERE empresa_id = :eid AND region_id = :rid AND vertical_interes = :vid
                   AND estado_embudo NOT IN ('ganado', 'perdido', 'invalido')
                 ORDER BY id DESC LIMIT 1",
                array('eid' => $empresaExistente['id'], 'rid' => $regionId, 'vid' => $verticalId)
            );
            if ($leadEmpresa) {
                $db->insert('actividades_crm', array(
                    'lead_id'    => $leadEmpresa['id'],
                    'usuario_id' => null,
                    'tipo'       => 'sistema',
                    'direccion'  => 'interna',
                    'asunto'     => 'Reingreso por API',
                    'detalles'   => 'Se recibió nuevamente esta empresa por la API de captación (origen: ' . $origen . '). No se creó duplicado.'
                ));
                $this->json(array(
                    'success'   => true,
                    'duplicado' => true,
                    'lead_id'   => (int)$leadEmpresa['id'],
                    'message'   => 'Esta empresa ya tiene un lead activo en esa región y vertical. Se registró el reingreso.'
                ));
            }
        }

        // ── Creación ─────────────────────────────────────────────────────────
        $db->beginTransaction();
        try {
            if ($empresaExistente) {
                $empresaId = $empresaExistente['id'];
            } else {
                $empresaId = $db->insert('empresas', array(
                    'rut'             => $rut,
                    'razon_social'    => $razon,
                    'nombre_fantasia' => $nombreEmpresa,
                    'giro'            => $giro !== '' ? $giro : null,
                    'region_id'       => $regionId,
                    'telefono'        => $telefono,
                    'email'           => $correo !== '' ? $correo : null
                ));
            }

            $contactoId = $db->insert('contactos', array(
                'empresa_id'   => $empresaId,
                'nombre'       => $nombre,
                'telefono'     => $telefono,
                'correo'       => $correo !== '' ? $correo : null,
                'es_principal' => 1
            ));

            $leadId = $db->insert('leads', array(
                'empresa_id'           => $empresaId,
                'contacto_id'          => $contactoId,
                'franquiciado_id'      => null,
                'usuario_asignado_id'  => null,
                'origen'               => $origen,
                'region_id'            => $regionId,
                'vertical_interes'     => $verticalId,
                'marca_interes'        => $marcaId > 0 ? $marcaId : null,
                'producto_interes'     => $productoId > 0 ? $productoId : null,
                'estado_embudo'        => ESTADO_NUEVO,
                'telefono_real'        => $telefono,
                'telefono_enmascarado' => enmascarar_telefono($telefono),
                'correo_real'          => $correo !== '' ? $correo : null,
                'correo_enmascarado'   => $correo !== '' ? enmascarar_correo($correo) : null,
                'datos_liberados'      => 0
            ));

            $db->insert('actividades_crm', array(
                'lead_id'    => $leadId,
                'usuario_id' => null,
                'tipo'       => 'sistema',
                'direccion'  => 'interna',
                'asunto'     => 'Lead captado vía API',
                'detalles'   => 'Lead recibido por la API de captación'
                    . ($franquiciaOrigen ? ' desde la landing de ' . $franquiciaOrigen['nombre_fantasia'] : '')
                    . '. Origen: ' . $origen . '.'
            ));

            if ($notas !== '') {
                $db->insert('actividades_crm', array(
                    'lead_id'    => $leadId,
                    'usuario_id' => null,
                    'tipo'       => 'nota',
                    'direccion'  => 'interna',
                    'asunto'     => 'Nota del formulario',
                    'detalles'   => $notas
                ));
            }

            // Asignación inmediata por cascada (respeta lo que cada franquiciado
            // puede VENDER: producto de interés, o la marca si no hay producto)
            $asignacion = RotacionHelper::asignarSiguiente($leadId, $regionId, $verticalId, $marcaId > 0 ? $marcaId : null, $productoId > 0 ? $productoId : null);

            $db->commit();

            $this->logApi('LEAD_OK', array('lead_id' => $leadId, 'asignado' => (bool)$asignacion));

            $respuesta = array(
                'success'  => true,
                'lead_id'  => (int)$leadId,
                'asignado' => (bool)$asignacion,
                'message'  => $asignacion
                    ? 'Lead creado y asignado a un franquiciado.'
                    : 'Lead creado. Quedó en espera de asignación (sin franquiciados calificados disponibles).'
            );
            if ($asignacion) {
                $respuesta['franquiciado_id'] = $asignacion['franquiciado_id'];
            }
            $this->json($respuesta, 201);

        } catch (Exception $e) {
            $db->rollBack();
            error_log('[API leads] Error: ' . $e->getMessage());
            $this->logApi('LEAD_ERROR', array('error' => $e->getMessage()));
            $this->json(array('success' => false, 'message' => 'Error interno al registrar el lead.'), 500);
        }
    }

    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Lee el payload como JSON o form-encoded.
     */
    private function leerPayload() {
        $contentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
        if (strpos($contentType, 'application/json') !== false) {
            $raw = file_get_contents('php://input');
            $json = json_decode($raw, true);
            return is_array($json) ? $json : array();
        }
        return $_POST;
    }

    private function logApi($evento, $datos) {
        $linea = '[' . date('Y-m-d H:i:s') . "] {$evento} " .
                 (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '-') . ' ' .
                 substr(json_encode($datos), 0, 1000) . PHP_EOL;
        @file_put_contents(LOG_DIR . '/api_leads.log', $linea, FILE_APPEND);
    }
}
