<?php
require_once __DIR__ . '/callcenter_test_helpers.php';
require_once __DIR__ . '/drive_test_orders.php';

function cc_test_allowed_states(): array
{
    return [
        'POR LLAMAR',
        'NO CONTESTA',
        'DEVOLVER LLAMADA',
        'REPROGRAMADO',
        'CONFIRMADO',
        'NO INTERESADO',
        'NUMERO EQUIVOCADO',
        'DUPLICADO',
    ];
}

if (!function_exists('cc_test_open_states')) {
    function cc_test_open_states(): array
    {
        return ['POR LLAMAR', 'NO CONTESTA', 'DEVOLVER LLAMADA', 'REPROGRAMADO'];
    }
}

if (!function_exists('cc_test_closed_states')) {
    function cc_test_closed_states(): array
    {
        return ['NO INTERESADO', 'NUMERO EQUIVOCADO', 'DUPLICADO'];
    }
}

function cc_test_state_badge_class(string $estado): string
{
    return match ($estado) {
        'CONFIRMADO' => 'bg-success-subtle text-success-emphasis',
        'DEVOLVER LLAMADA', 'REPROGRAMADO' => 'bg-info-subtle text-info-emphasis',
        'NO CONTESTA' => 'bg-secondary-subtle text-secondary-emphasis',
        'NO INTERESADO', 'NUMERO EQUIVOCADO', 'DUPLICADO' => 'bg-danger-subtle text-danger-emphasis',
        default => 'bg-warning-subtle text-warning-emphasis',
    };
}

function cc_test_display_value(?string $value, string $fallback = 'No registrado'): string
{
    $value = trim((string) $value);
    return $value !== '' ? $value : $fallback;
}

function cc_test_format_price(?string $value): string
{
    $value = trim((string) $value);
    return $value !== '' ? 'S/ ' . $value : 'No registrado';
}

function cc_test_parse_datetime(?string $value): ?string
{
    $value = trim((string) $value);
    if ($value === '') {
        return null;
    }

    $formats = [
        'Y-m-d\\TH:i',
        'Y-m-d H:i:s',
        'Y-m-d H:i',
        DateTimeInterface::ATOM,
        'Y-m-d',
    ];

    foreach ($formats as $format) {
        $date = DateTimeImmutable::createFromFormat($format, $value);
        if ($date instanceof DateTimeImmutable) {
            return $date->format('Y-m-d H:i:s');
        }
    }

    try {
        return (new DateTimeImmutable($value))->format('Y-m-d H:i:s');
    } catch (Throwable $exception) {
        return null;
    }
}

function cc_test_format_datetime(?string $value, string $fallback = 'Sin programar'): string
{
    $parsed = cc_test_parse_datetime($value);
    if ($parsed === null) {
        return $fallback;
    }

    try {
        return (new DateTimeImmutable($parsed))->format('d/m/Y h:i A');
    } catch (Throwable $exception) {
        return $fallback;
    }
}

function cc_test_format_datetime_local(?string $value): string
{
    $parsed = cc_test_parse_datetime($value);
    if ($parsed === null) {
        return '';
    }

    try {
        return (new DateTimeImmutable($parsed))->format('Y-m-d\\TH:i');
    } catch (Throwable $exception) {
        return '';
    }
}

if (!function_exists('cc_test_table_exists')) {
    function cc_test_table_exists(PDO $pdo, string $tableName): bool
    {
        static $cache = [];

        if (array_key_exists($tableName, $cache)) {
            return $cache[$tableName];
        }

        $stmt = $pdo->prepare('SHOW TABLES LIKE ?');
        $stmt->execute([$tableName]);
        $cache[$tableName] = (bool) $stmt->fetchColumn();

        return $cache[$tableName];
    }
}

function cc_test_column_exists(PDO $pdo, string $tableName, string $columnName): bool
{
    static $cache = [];
    $cacheKey = $tableName . '.' . $columnName;

    if (array_key_exists($cacheKey, $cache)) {
        return $cache[$cacheKey];
    }

    $stmt = $pdo->prepare("SHOW COLUMNS FROM `{$tableName}` LIKE ?");
    $stmt->execute([$columnName]);
    $cache[$cacheKey] = (bool) $stmt->fetchColumn();

    return $cache[$cacheKey];
}

function cc_test_add_column_if_missing(PDO $pdo, string $tableName, string $columnName, string $definition): void
{
    if (!cc_test_column_exists($pdo, $tableName, $columnName)) {
        $pdo->exec("ALTER TABLE `{$tableName}` ADD COLUMN `{$columnName}` {$definition}");
    }
}

function cc_test_ensure_schema(PDO $pdo): void
{
    static $checked = false;
    if ($checked) {
        return;
    }

    $pdo->exec("CREATE TABLE IF NOT EXISTS `callcenter_test_orders` (
        `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        `source_key` CHAR(40) NOT NULL,
        `codigo` VARCHAR(80) DEFAULT NULL,
        `import_id` VARCHAR(120) DEFAULT NULL,
        `drive_imported_at` DATETIME NULL,
        `nombre` VARCHAR(255) DEFAULT NULL,
        `direccion_drive` TEXT NULL,
        `referencia_drive` TEXT NULL,
        `sede_drive` VARCHAR(120) NULL,
        `ciudad_drive` VARCHAR(120) NULL,
        `distrito_drive` VARCHAR(120) NULL,
        `dni_drive` LONGTEXT NULL,
        `observaciones_drive` TEXT NULL,
        `celular` VARCHAR(40) DEFAULT NULL,
        `producto` TEXT NULL,
        `cantidad` VARCHAR(60) NULL,
        `precio` VARCHAR(60) NULL,
        `pais` VARCHAR(80) NULL,
        `coordenadas` VARCHAR(255) NULL,
        `metodo` VARCHAR(120) NULL,
        `first_seen_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        `last_seen_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY `uniq_callcenter_test_orders_source_key` (`source_key`),
        KEY `idx_callcenter_test_orders_drive_imported_at` (`drive_imported_at`),
        KEY `idx_callcenter_test_orders_last_seen_at` (`last_seen_at`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

    // Asegurar que `dni_drive` soporte valores grandes (evita SQLSTATE[22001] por truncamiento).
    try {
        $colStmt = $pdo->prepare("
            SELECT DATA_TYPE
            FROM information_schema.COLUMNS
            WHERE TABLE_SCHEMA = DATABASE()
              AND TABLE_NAME = 'callcenter_test_orders'
              AND COLUMN_NAME = 'dni_drive'
            LIMIT 1
        ");
        $colStmt->execute();
        $dataType = strtolower((string) $colStmt->fetchColumn());

        if ($dataType !== 'longtext') {
            $pdo->exec("ALTER TABLE `callcenter_test_orders` MODIFY COLUMN `dni_drive` LONGTEXT NULL");
        }
    } catch (Throwable $exception) {
        error_log('cc_test_ensure_schema: ' . $exception->getMessage());
    }

    $pdo->exec("CREATE TABLE IF NOT EXISTS `callcenter_test_tracking` (
        `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        `source_key` CHAR(40) NOT NULL,
        `estado` VARCHAR(40) NOT NULL DEFAULT 'POR LLAMAR',
        `nota_seguimiento` TEXT NULL,
        `proxima_llamada` DATETIME NULL,
        `fecha_ultimo_contacto` DATETIME NULL,
        `direccion_editada` TEXT NULL,
        `referencia_editada` TEXT NULL,
        `sede_editada` VARCHAR(120) NULL,
        `ciudad_editada` VARCHAR(120) NULL,
        `distrito_editado` VARCHAR(120) NULL,
        `dni_editado` VARCHAR(40) NULL,
        `observaciones_editadas` TEXT NULL,
        `user_id` INT NULL,
        `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY `uniq_callcenter_test_tracking_source_key` (`source_key`),
        KEY `idx_callcenter_test_tracking_estado` (`estado`),
        KEY `idx_callcenter_test_tracking_proxima` (`proxima_llamada`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'proxima_llamada', 'DATETIME NULL AFTER `nota_seguimiento`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'fecha_ultimo_contacto', 'DATETIME NULL AFTER `proxima_llamada`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'direccion_editada', 'TEXT NULL AFTER `fecha_ultimo_contacto`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'referencia_editada', 'TEXT NULL AFTER `direccion_editada`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'sede_editada', 'VARCHAR(120) NULL AFTER `referencia_editada`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'ciudad_editada', 'VARCHAR(120) NULL AFTER `sede_editada`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'distrito_editado', 'VARCHAR(120) NULL AFTER `ciudad_editada`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'dni_editado', 'VARCHAR(40) NULL AFTER `distrito_editado`');
    cc_test_add_column_if_missing($pdo, 'callcenter_test_tracking', 'observaciones_editadas', 'TEXT NULL AFTER `dni_editado`');

    if (cc_test_table_exists($pdo, 'historial_llamadas')) {
        cc_test_add_column_if_missing($pdo, 'historial_llamadas', 'pedido_id', 'VARCHAR(80) NULL');
        cc_test_add_column_if_missing($pdo, 'historial_llamadas', 'asesor_id', 'INT NULL');
        cc_test_add_column_if_missing($pdo, 'historial_llamadas', 'resultado', 'VARCHAR(120) NULL');
        cc_test_add_column_if_missing($pdo, 'historial_llamadas', 'observacion', 'TEXT NULL');
        cc_test_add_column_if_missing($pdo, 'historial_llamadas', 'fecha_llamada', 'DATETIME NULL DEFAULT CURRENT_TIMESTAMP');
    } else {
        $pdo->exec("CREATE TABLE IF NOT EXISTS `historial_llamadas` (
            `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
            `pedido_id` VARCHAR(80) NOT NULL,
            `asesor_id` INT NULL,
            `resultado` VARCHAR(120) NOT NULL,
            `observacion` TEXT NULL,
            `fecha_llamada` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            INDEX `idx_historial_llamadas_pedido` (`pedido_id`),
            INDEX `idx_historial_llamadas_asesor` (`asesor_id`),
            INDEX `idx_historial_llamadas_fecha` (`fecha_llamada`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
    }

    $checked = true;
}

function cc_test_sync_orders_from_drive(PDO $pdo, int $limit = 250): array
{
    cc_test_ensure_schema($pdo);

    $preview = drive_test_fetch_orders($limit);
    $orders = $preview['orders'] ?? [];

    if (empty($orders)) {
        return [
            'synced_count' => 0,
            'total_rows' => (int) ($preview['total_rows'] ?? 0),
        ];
    }

    $stmt = $pdo->prepare(
        'INSERT INTO callcenter_test_orders (
            source_key, codigo, import_id, drive_imported_at, nombre,
            direccion_drive, referencia_drive, sede_drive, ciudad_drive, distrito_drive,
            dni_drive, observaciones_drive, celular, producto, cantidad, precio,
            pais, coordenadas, metodo
        ) VALUES (
            :source_key, :codigo, :import_id, :drive_imported_at, :nombre,
            :direccion_drive, :referencia_drive, :sede_drive, :ciudad_drive, :distrito_drive,
            :dni_drive, :observaciones_drive, :celular, :producto, :cantidad, :precio,
            :pais, :coordenadas, :metodo
        )
        ON DUPLICATE KEY UPDATE
            codigo = VALUES(codigo),
            import_id = VALUES(import_id),
            drive_imported_at = VALUES(drive_imported_at),
            nombre = VALUES(nombre),
            direccion_drive = VALUES(direccion_drive),
            referencia_drive = VALUES(referencia_drive),
            sede_drive = VALUES(sede_drive),
            ciudad_drive = VALUES(ciudad_drive),
            distrito_drive = VALUES(distrito_drive),
            dni_drive = VALUES(dni_drive),
            observaciones_drive = VALUES(observaciones_drive),
            celular = VALUES(celular),
            producto = VALUES(producto),
            cantidad = VALUES(cantidad),
            precio = VALUES(precio),
            pais = VALUES(pais),
            coordenadas = VALUES(coordenadas),
            metodo = VALUES(metodo),
            last_seen_at = CURRENT_TIMESTAMP'
    );

    foreach ($orders as $order) {
        $stmt->execute([
            ':source_key' => $order['source_key'],
            ':codigo' => $order['codigo'] ?: null,
            ':import_id' => $order['import_id'] ?: null,
            ':drive_imported_at' => cc_test_parse_datetime($order['import_id'] ?? ''),
            ':nombre' => $order['nombre'] ?: null,
            ':direccion_drive' => $order['direccion'] ?: null,
            ':referencia_drive' => $order['referencia'] ?: null,
            ':sede_drive' => $order['sede'] ?: null,
            ':ciudad_drive' => $order['ciudad'] ?: null,
            ':distrito_drive' => $order['distrito'] ?: null,
            ':dni_drive' => $order['dni'] ?: null,
            ':observaciones_drive' => $order['observaciones'] ?: null,
            ':celular' => $order['celular'] ?: null,
            ':producto' => $order['producto'] ?: null,
            ':cantidad' => $order['cantidad'] ?: null,
            ':precio' => $order['precio'] ?: null,
            ':pais' => $order['pais'] ?: null,
            ':coordenadas' => $order['coordenadas'] ?: null,
            ':metodo' => $order['metodo'] ?: null,
        ]);
    }

    return [
        'synced_count' => count($orders),
        'total_rows' => (int) ($preview['total_rows'] ?? 0),
    ];
}

function cc_test_fetch_dashboard_orders(PDO $pdo): array
{
    cc_test_ensure_schema($pdo);

    $sql = "SELECT
        o.source_key,
        o.codigo,
        o.import_id,
        o.drive_imported_at,
        o.nombre,
        o.celular,
        o.producto,
        o.cantidad,
        o.precio,
        o.pais,
        o.coordenadas,
        o.metodo,
        o.direccion_drive,
        o.referencia_drive,
        o.sede_drive,
        o.ciudad_drive,
        o.distrito_drive,
        o.dni_drive,
        o.observaciones_drive,
        o.first_seen_at,
        o.last_seen_at,
        COALESCE(NULLIF(t.estado, ''), 'POR LLAMAR') AS estado,
        COALESCE(t.nota_seguimiento, '') AS nota_seguimiento,
        t.proxima_llamada,
        t.fecha_ultimo_contacto,
        t.user_id,
        t.updated_at AS tracking_updated_at,
        t.direccion_editada,
        t.referencia_editada,
        t.sede_editada,
        t.ciudad_editada,
        t.distrito_editado,
        t.dni_editado,
        t.observaciones_editadas,
        COALESCE(NULLIF(t.direccion_editada, ''), NULLIF(o.direccion_drive, '')) AS direccion_final,
        COALESCE(NULLIF(t.referencia_editada, ''), NULLIF(o.referencia_drive, '')) AS referencia_final,
        COALESCE(NULLIF(t.sede_editada, ''), NULLIF(o.sede_drive, '')) AS sede_final,
        COALESCE(NULLIF(t.ciudad_editada, ''), NULLIF(o.ciudad_drive, '')) AS ciudad_final,
        COALESCE(NULLIF(t.distrito_editado, ''), NULLIF(o.distrito_drive, '')) AS distrito_final,
        COALESCE(NULLIF(t.dni_editado, ''), NULLIF(o.dni_drive, '')) AS dni_final,
        COALESCE(NULLIF(t.observaciones_editadas, ''), NULLIF(o.observaciones_drive, '')) AS observaciones_final,
        IFNULL(c.total_llamadas, 0) AS total_llamadas,
        c.ultima_llamada,
        COALESCE(u.nombre_asesor, u.username, '') AS gestor
    FROM callcenter_test_orders o
    LEFT JOIN callcenter_test_tracking t ON t.source_key = o.source_key
    LEFT JOIN (
        SELECT pedido_id, COUNT(*) AS total_llamadas, MAX(fecha_llamada) AS ultima_llamada
        FROM historial_llamadas
        GROUP BY pedido_id
    ) c ON c.pedido_id = o.source_key
    LEFT JOIN users u ON u.id = t.user_id
    ORDER BY COALESCE(o.drive_imported_at, o.first_seen_at) DESC, o.id DESC";

    $stmt = $pdo->query($sql);
    $orders = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach ($orders as &$order) {
        $digits = preg_replace('/\D+/', '', (string) ($order['celular'] ?? ''));
        $order['telefono_url'] = $digits !== '' ? 'tel:' . $digits : '';
        $order['whatsapp_url'] = $digits !== '' ? 'https://wa.me/' . $digits : '';
    }
    unset($order);

    return $orders;
}

function cc_test_is_same_day(?string $value, DateTimeImmutable $day): bool
{
    $parsed = cc_test_parse_datetime($value);
    if ($parsed === null) {
        return false;
    }

    try {
        return (new DateTimeImmutable($parsed))->format('Y-m-d') === $day->format('Y-m-d');
    } catch (Throwable $exception) {
        return false;
    }
}

function cc_test_is_due_today(array $order, DateTimeImmutable $endOfToday): bool
{
    if (!in_array($order['estado'] ?? '', cc_test_open_states(), true)) {
        return false;
    }

    $nextCall = cc_test_parse_datetime($order['proxima_llamada'] ?? null);
    if ($nextCall === null) {
        return true;
    }

    try {
        return new DateTimeImmutable($nextCall) <= $endOfToday;
    } catch (Throwable $exception) {
        return true;
    }
}

function cc_test_matches_search(array $order, string $search): bool
{
    $search = trim($search);
    if ($search === '') {
        return true;
    }

    $haystack = mb_strtolower(implode(' ', [
        $order['codigo'] ?? '',
        $order['nombre'] ?? '',
        $order['celular'] ?? '',
        $order['dni_final'] ?? '',
        $order['direccion_final'] ?? '',
        $order['distrito_final'] ?? '',
        $order['ciudad_final'] ?? '',
        $order['producto'] ?? '',
    ]));

    return str_contains($haystack, mb_strtolower($search));
}

function cc_test_build_dashboard(array $orders, string $view, string $search = ''): array
{
    $today = new DateTimeImmutable('today');
    $endOfToday = $today->setTime(23, 59, 59);
    $stats = [
        'todos' => count($orders),
        'nuevos_hoy' => 0,
        'pendientes_hoy' => 0,
        'confirmados' => 0,
        'cerrados' => 0,
    ];
    $visibleOrders = [];

    foreach ($orders as $order) {
        $createdReference = $order['drive_imported_at'] ?: $order['first_seen_at'];
        $isNewToday = cc_test_is_same_day($createdReference, $today);
        $isConfirmed = ($order['estado'] ?? '') === 'CONFIRMADO';
        $isClosed = in_array($order['estado'] ?? '', cc_test_closed_states(), true);
        $isPendingToday = cc_test_is_due_today($order, $endOfToday);

        if ($isNewToday) {
            $stats['nuevos_hoy']++;
        }
        if ($isPendingToday) {
            $stats['pendientes_hoy']++;
        }
        if ($isConfirmed) {
            $stats['confirmados']++;
        }
        if ($isClosed) {
            $stats['cerrados']++;
        }

        $order['is_new_today'] = $isNewToday;
        $order['is_pending_today'] = $isPendingToday;
        $order['is_confirmed'] = $isConfirmed;
        $order['is_closed'] = $isClosed;

        $matchesView = match ($view) {
            'nuevos_hoy' => $isNewToday,
            'confirmados' => $isConfirmed,
            'cerrados' => $isClosed,
            'todos' => true,
            default => $isPendingToday,
        };

        if ($matchesView && cc_test_matches_search($order, $search)) {
            $visibleOrders[] = $order;
        }
    }

    usort($visibleOrders, static function (array $a, array $b) use ($view): int {
        $aNext = cc_test_parse_datetime($a['proxima_llamada'] ?? null);
        $bNext = cc_test_parse_datetime($b['proxima_llamada'] ?? null);

        if ($view === 'pendientes_hoy') {
            if ($aNext === null && $bNext !== null) {
                return -1;
            }
            if ($aNext !== null && $bNext === null) {
                return 1;
            }
            if ($aNext !== null && $bNext !== null && $aNext !== $bNext) {
                return strcmp($aNext, $bNext);
            }
        }

        $aBase = cc_test_parse_datetime($a['drive_imported_at'] ?? null) ?: cc_test_parse_datetime($a['first_seen_at'] ?? null) ?: '';
        $bBase = cc_test_parse_datetime($b['drive_imported_at'] ?? null) ?: cc_test_parse_datetime($b['first_seen_at'] ?? null) ?: '';
        return strcmp($bBase, $aBase);
    });

    return [
        'stats' => $stats,
        'visible_orders' => $visibleOrders,
    ];
}

function cc_test_fetch_histories(PDO $pdo, array $sourceKeys): array
{
    if (empty($sourceKeys)) {
        return [];
    }

    $placeholders = implode(',', array_fill(0, count($sourceKeys), '?'));
    $sql = "SELECT h.*, COALESCE(u.nombre_asesor, u.username, CONCAT('Asesor #', h.asesor_id)) AS asesor
            FROM historial_llamadas h
            LEFT JOIN users u ON u.id = h.asesor_id
            WHERE h.pedido_id IN ($placeholders)
            ORDER BY h.fecha_llamada DESC, h.id DESC";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($sourceKeys);

    $histories = [];
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $histories[$row['pedido_id']][] = $row;
    }

    return $histories;
}
