<?php
/**
 * POST /modules/turnero/api/create_turno.php
 * Genera un nuevo turno desde el kiosko o recepción.
 * No requiere login (kiosko es público).
 *
 * Body JSON:
 *   prioridad_codigo  string  requerido   "A"|"B"|"C"|"D"|"E"|"F"
 *   paciente_nombre   string  opcional
 *   paciente_cel      string  opcional
 */

require_once __DIR__ . '/_helpers.php';
requireMethod('POST');

// Este endpoint es público (kiosko no requiere login)
// Solo validamos CSRF básico: debe ser POST con JSON

$datos = inputJson();

// ── Validación ────────────────────────────────────────────────
$prioCodigo = strtoupper(trim($datos['prioridad_codigo'] ?? ''));
if (!in_array($prioCodigo, ['A', 'B', 'C', 'D', 'E', 'F'], true)) {
    jsonError('prioridad_codigo inválido. Use A, B, C, D, E o F.');
}

$pacienteDoc   = substr(trim($datos['paciente_nombre'] ?? ''), 0, 150);
$pacienteCel   = preg_replace('/[^0-9+\- ]/', '', $datos['paciente_cel'] ?? '');
$pacienteCel   = substr($pacienteCel, 0, 20);

// ── Lógica principal (dentro de transacción para evitar race conditions) ──
$pdo = db();
$pdo->beginTransaction();

try {
    $sesionId = obtenerOCrearSesionHoy();

    // Lock de sesión para serializar la creación de turnos
    $pdo->prepare('SELECT id FROM turnero_sesiones WHERE id = ? FOR UPDATE')
        ->execute([$sesionId]);

    // Buscar prioridad_id
    $stmt = $pdo->prepare(
        'SELECT id FROM turnero_prioridades WHERE codigo = ? AND activo = 1 LIMIT 1'
    );
    $stmt->execute([$prioCodigo]);
    $prioridad = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$prioridad) {
        $pdo->rollBack();
        jsonError("La prioridad '$prioCodigo' no existe o no está activa.", 422);
    }

    $prioridadId = (int) $prioridad['id'];

    // Buscar paciente por número de documento en lab_pacientes
    $pacienteNombre = $pacienteDoc;
    $pacienteId     = null;
    $pacienteTel    = $pacienteCel; // fallback: celular del kiosko
    if ($pacienteDoc) {
        try {
            $stmtP = $pdo->prepare(
                'SELECT id, nombre_completo, telefono FROM lab_pacientes WHERE numero_documento = ? AND is_active = 1 LIMIT 1'
            );
            $stmtP->execute([$pacienteDoc]);
            $pacRow = $stmtP->fetch(PDO::FETCH_ASSOC);
            if ($pacRow) {
                $pacienteNombre = $pacRow['nombre_completo'];
                $pacienteId     = (int) $pacRow['id'];
                $pacienteTel    = $pacRow['telefono'] ?: $pacienteCel;
            }
        } catch (\Throwable $e) {
            $pacienteNombre = $pacienteDoc;
        }
    }

    // Validar que el paciente no tenga un turno activo en la sesión de hoy
    if ($pacienteId) {
        $stmtDup = $pdo->prepare(
            "SELECT codigo, estado FROM turnero_turnos
              WHERE paciente_id = ? AND sesion_id = ?
                AND estado NOT IN ('finalizado','ausente','cancelado')
              LIMIT 1"
        );
        $stmtDup->execute([$pacienteId, $sesionId]);
        $dupTurno = $stmtDup->fetch(PDO::FETCH_ASSOC);
        if ($dupTurno) {
            $pdo->rollBack();
            jsonError(
                "El paciente ya tiene un turno activo: {$dupTurno['codigo']} (estado: {$dupTurno['estado']}). " .
                "Debe finalizar o cancelar el turno actual antes de tomar uno nuevo.",
                409
            );
        }
    }

    // Correlativo independiente por prioridad (A-001, A-002... B-001, B-002... etc.)
    $numero = siguienteNumeroPorPrioridad($sesionId, $prioridadId);

    // Código visual: "A001", "B001", "E001", etc.
    $codigo = $prioCodigo . str_pad($numero, 3, '0', STR_PAD_LEFT);

    $stmt = $pdo->prepare(
        'INSERT INTO turnero_turnos
            (sesion_id, numero, codigo, prioridad_id, paciente_nombre, paciente_cel, paciente_id,
             estado, creado_at)
         VALUES
            (?, ?, ?, ?, ?, ?, ?, "espera", NOW())'
    );
    $stmt->execute([
        $sesionId,
        $numero,
        $codigo,
        $prioridadId,
        $pacienteNombre ?: null,
        $pacienteCel    ?: null,
        $pacienteId,
    ]);

    $turnoId = (int) $pdo->lastInsertId();
    $pdo->commit();

    // ── Prioridad F: saltar recepción, ir directo a toma de muestras ──
    $esSoloMuestra = ($prioCodigo === 'F');
    if ($esSoloMuestra) {
        try {
            $stmtLugar = $pdo->prepare(
                "SELECT id FROM turnero_lugares WHERE tipo = 'muestras' AND activo = 1 ORDER BY sort_order ASC LIMIT 1"
            );
            $stmtLugar->execute();
            $lugarMuestras = $stmtLugar->fetchColumn();
            if ($lugarMuestras) {
                $pdo->prepare(
                    "UPDATE turnero_turnos
                        SET estado = 'en_espera_lugar',
                            lugar_destino_id = ?,
                            fin_recepcion_at = NOW()
                      WHERE id = ?"
                )->execute([(int)$lugarMuestras, $turnoId]);
                notificarSSE($sesionId);
            }
        } catch (\Throwable $_) {}
    }

    notificarSSE($sesionId);

    // ── Crear registro de consentimiento (siempre, con o sin teléfono) ──
    $enlaceConsentimiento = null;
    if (!$esSoloMuestra) {
        try {
            $stmtForms = $pdo->prepare(
                "SELECT tlc.formulario_id, l.formulario_modo
                   FROM turnero_lugar_consentimientos tlc
                   JOIN lab_formularios f ON f.id = tlc.formulario_id AND f.is_active = 1
                   JOIN turnero_lugares l ON l.id = tlc.lugar_id AND l.tipo = 'recepcion' AND l.activo = 1
                  ORDER BY tlc.formulario_id ASC
                  LIMIT 1"
            );
            $stmtForms->execute();
            $formRow = $stmtForms->fetch(\PDO::FETCH_ASSOC);

            if ($formRow) {
                $conToken = sprintf(
                    '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
                    mt_rand(0,0xffff), mt_rand(0,0xffff),
                    mt_rand(0,0xffff),
                    mt_rand(0,0x0fff)|0x4000,
                    mt_rand(0,0x3fff)|0x8000,
                    mt_rand(0,0xffff), mt_rand(0,0xffff), mt_rand(0,0xffff)
                );
                $pdo->prepare(
                    "INSERT IGNORE INTO turnero_consentimientos
                        (turno_id, formulario_id, token, estado)
                     VALUES (?, ?, ?, 'pendiente')"
                )->execute([$turnoId, (int)$formRow['formulario_id'], $conToken]);

                // Solo generar enlace si el modo es 'link' (embebido no usa WA)
                if (($formRow['formulario_modo'] ?? 'link') === 'link') {
                    $baseUrl = defined('BASE_URL') ? rtrim(BASE_URL, '/') : '';
                    // Forzar HTTPS: Android WhatsApp CCT bloquea páginas HTTP
                    $baseUrl = preg_replace('#^http://#', 'https://', $baseUrl);
                    $enlaceConsentimiento = $baseUrl . '/ver_formulario_enviado.php?token=' . urlencode($conToken);
                }
            }
        } catch (\Throwable $e) {
            // Sin consentimiento disponible, continuar sin link
        }
    }

    // ── Enviar notificación WhatsApp ──
    if ($pacienteTel) {
        try {
            $stmtCfg = $pdo->prepare(
                "SELECT clave, valor FROM lab_config WHERE clave IN ('turnero_wa_template','turnero_wa_template_muestra','turnero_wa_lang','turnero_wa_kiosko_enabled')"
            );
            $stmtCfg->execute();
            $cfgWA = $stmtCfg->fetchAll(PDO::FETCH_KEY_PAIR);
            $waKioskoEnabled = ($cfgWA['turnero_wa_kiosko_enabled'] ?? '0') === '1';
            $waTemplate = $esSoloMuestra
                ? ($cfgWA['turnero_wa_template_muestra'] ?? 'turno_muestra_pendiente')
                : ($cfgWA['turnero_wa_template'] ?? 'consentimiento_turno');
            // Usar idioma real de la plantilla aprobada (puede diferir del config)
            $stmtLang = $pdo->prepare("SELECT language_code FROM message_templates WHERE template_name = ? LIMIT 1");
            $stmtLang->execute([$waTemplate]);
            $waLang = $stmtLang->fetchColumn() ?: ($cfgWA['turnero_wa_lang'] ?? 'es');
        } catch (\Throwable $e) {
            $waKioskoEnabled = true;
            $waTemplate      = 'consentimiento_turno';
            $waLang          = 'es';
        }
    }

    if ($pacienteTel && $waKioskoEnabled) {
        // WhatsAppService::formatPhoneNumber maneja el formato colombiano correctamente
        $cel = preg_replace('/[^0-9]/', '', $pacienteTel);

        // Marcar como enviado si vamos a mandar WA
        if ($enlaceConsentimiento) {
            try {
                $pdo->prepare(
                    "UPDATE turnero_consentimientos SET estado='enviado', enviado_at=NOW()
                      WHERE turno_id=? AND estado='pendiente'"
                )->execute([$turnoId]);
            } catch (\Throwable $_) {}
        }

        require_once __DIR__ . '/../../../services/WhatsAppService.php';
        $nombreWA = $pacienteNombre ?: 'Paciente';
        $waMeta   = ['canal' => 'turnero'];
        try {
            $wa = new WhatsAppService('turnero');
            $rawComps = [
                ['type' => 'body', 'parameters' => [['type' => 'text', 'text' => $codigo]]]
            ];
            if ($conToken) {
                $rawComps[] = [
                    'type'       => 'button',
                    'sub_type'   => 'url',
                    'index'      => '0',
                    'parameters' => [['type' => 'text', 'text' => $conToken]],
                ];
            }
            $wa->sendTemplateMessage($cel, $waTemplate, $waLang, [], [], $rawComps, $waMeta);
        } catch (\Throwable $eTmpl) {
            try {
                $msg = "Hola {$nombreWA}, su turno *{$codigo}* ha sido registrado.";
                if ($enlaceConsentimiento) {
                    $msg .= "\n\nPor favor firme su consentimiento informado antes de ser atendido:\n{$enlaceConsentimiento}";
                }
                $wa->sendTextMessage($cel, $msg, $waMeta);
            } catch (\Throwable $eTxt) {
                // Silenciar
            }
        }
    }

    // Contar posición en la cola
    $stmt = $pdo->prepare(
        '
        SELECT COUNT(*) AS posicion
          FROM turnero_turnos t
          JOIN turnero_prioridades p ON p.id = t.prioridad_id
         WHERE t.estado = "espera"
           AND t.sesion_id = ?
           AND (
               p.orden_peso < (SELECT orden_peso FROM turnero_prioridades WHERE id = ?)
               OR (
                   p.orden_peso = (SELECT orden_peso FROM turnero_prioridades WHERE id = ?)
                   AND t.creado_at < (SELECT creado_at FROM turnero_turnos WHERE id = ?)
               )
           )
        '
    );
    $stmt->execute([$sesionId, $prioridadId, $prioridadId, $turnoId]);
    $posicion = (int) $stmt->fetchColumn() + 1;

    jsonOk([
        'turno' => [
            'id'               => $turnoId,
            'codigo'           => $codigo,
            'numero'           => $numero,
            'prioridad_codigo' => $prioCodigo,
            'posicion_cola'    => $posicion,
            'sesion_id'        => $sesionId,
            'paciente_nombre'  => $pacienteNombre ?: $pacienteDoc,
        ],
    ], "Turno $codigo asignado correctamente");

} catch (\Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    jsonError('Error al crear el turno: ' . $e->getMessage(), 500);
}
