<?php
// Endpoint: asignación masiva de leads a empleados de un desk
session_start();
define('BASE_PATH', dirname(__DIR__, 2));
require_once BASE_PATH . '/database/config.php';
require_once BASE_PATH . '/database/connection.php';

function isLoggedIn() {
    return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']);
}

header('Content-Type: application/json; charset=utf-8');

if (!isLoggedIn()) {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'No autorizado']);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['success' => false, 'message' => 'Método no permitido']);
    exit;
}

$lead_ids = isset($_POST['lead_ids']) ? (array)$_POST['lead_ids'] : [];
$desk_id = isset($_POST['desk_id']) ? intval($_POST['desk_id']) : 0;
$user_ids = isset($_POST['user_ids']) ? (array)$_POST['user_ids'] : [];
$status = $_POST['status'] ?? '';

// Validaciones básicas
if (empty($lead_ids) || $desk_id <= 0 || empty($user_ids) || $status === '') {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Parámetros inválidos']);
    exit;
}

// Normalizar arrays a enteros
$lead_ids = array_values(array_filter(array_map('intval', $lead_ids), function($v){ return $v > 0; }));
$user_ids = array_values(array_filter(array_map('intval', $user_ids), function($v){ return $v > 0; }));

if (empty($lead_ids) || empty($user_ids)) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Listas de IDs inválidas']);
    exit;
}

$db = getDB();
$pdo = $db->getConnection();

try {
    // Migración defensiva: si leads.status es ENUM, convertirlo a VARCHAR(50)
    try {
        $stmtCol = $pdo->prepare("SELECT DATA_TYPE, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'leads' AND COLUMN_NAME = 'status' LIMIT 1");
        $stmtCol->execute([DB_NAME]);
        $col = $stmtCol->fetch(PDO::FETCH_ASSOC);
        if ($col && (strtolower($col['DATA_TYPE'] ?? '') === 'enum' || stripos($col['COLUMN_TYPE'] ?? '', 'enum(') === 0)) {
            $pdo->exec("ALTER TABLE leads MODIFY status VARCHAR(50) NOT NULL DEFAULT 'new'");
        }
    } catch (Exception $migEx) {
        // No bloquear si falla la migración; se informará más adelante si ocurre un error al actualizar
    }

    // Verificar permiso: leads.assign
    if (!function_exists('userHasPermissionByName')) {
        function userHasPermissionByName($pdo, $permName, $userId) {
            if (empty($userId)) return false;
            $stmt = $pdo->prepare("SELECT 1 FROM role_permissions rp INNER JOIN permissions p ON rp.permission_id = p.id INNER JOIN user_roles ur ON rp.role_id = ur.role_id WHERE ur.user_id = ? AND p.name = ? LIMIT 1");
            $stmt->execute([$userId, $permName]);
            return (bool)$stmt->fetchColumn();
        }
    }
    $current_user_id = (int)($_SESSION['user_id'] ?? 0);
    if (!userHasPermissionByName($pdo, 'leads.assign', $current_user_id)) {
        http_response_code(403);
        echo json_encode(['success' => false, 'message' => 'Permiso requerido: leads.assign']);
        exit;
    }
    // Validar desk
    $desk = $db->selectOne("SELECT id, name FROM desks WHERE id = ? AND status = 'active'", [$desk_id]);
    if (!$desk) {
        http_response_code(404);
        echo json_encode(['success' => false, 'message' => 'Desk no encontrado o inactivo']);
        exit;
    }

    // Validar que usuarios pertenecen al desk (filtrar si no)
    $placeholders = str_repeat('?,', count($user_ids) - 1) . '?';
    $params = $user_ids;
    array_unshift($params, $desk_id);
    $valid_users = $db->select(
        "SELECT u.id FROM users u INNER JOIN desk_users du ON du.user_id = u.id WHERE du.desk_id = ? AND u.id IN ($placeholders) AND u.status = 'active'",
        $params
    );
    $valid_user_ids = array_map(function($r){ return (int)$r['id']; }, $valid_users);
    if (empty($valid_user_ids)) {
        http_response_code(400);
        echo json_encode(['success' => false, 'message' => 'No hay usuarios válidos vinculados al desk']);
        exit;
    }

    // Validar formato de estado y que esté permitido por el desk
    if (!is_string($status) || !preg_match('/^[a-z0-9_\-]{2,50}$/', $status)) {
        http_response_code(400);
        echo json_encode(['success' => false, 'message' => 'Formato de estado inválido']);
        exit;
    }
    $allowedRows = $db->select("SELECT status FROM desk_allowed_statuses WHERE desk_id = ?", [$desk_id]);
    $allowed = array_map(function($r){ return $r['status']; }, $allowedRows ?: []);
    if (empty($allowed) || !in_array($status, $allowed, true)) {
        http_response_code(400);
        echo json_encode(['success' => false, 'message' => 'Estado no permitido para el desk seleccionado']);
        exit;
    }

    // Preparar distribución
    $nLeads = count($lead_ids);
    $nUsers = count($valid_user_ids);
    $distribution = [];
    if ($nUsers === 1) {
        $distribution[$valid_user_ids[0]] = $nLeads;
    } else {
        $base = intdiv($nLeads, $nUsers);
        $rem = $nLeads % $nUsers;
        foreach ($valid_user_ids as $idx => $uid) {
            $distribution[$uid] = $base + ($idx < $rem ? 1 : 0);
        }
    }

    // Ejecutar asignación
    $pdo->beginTransaction();

    // Obtener datos actuales para historial y comparación
    $placeholdersLeads = str_repeat('?,', count($lead_ids) - 1) . '?';
    $currentRows = $db->select("SELECT id, status, assigned_to, desk_id FROM leads WHERE id IN ($placeholdersLeads)", $lead_ids);
    $byLead = [];
    foreach ($currentRows as $row) {
        $byLead[(int)$row['id']] = [
            'status' => $row['status'],
            'assigned_to' => isset($row['assigned_to']) ? (int)$row['assigned_to'] : null,
            'desk_id' => isset($row['desk_id']) ? (int)$row['desk_id'] : null,
        ];
    }
    $existingLeadIds = array_map('intval', array_keys($byLead));
    $missingLeadIds = array_values(array_diff($lead_ids, $existingLeadIds));

    $leadIdx = 0;
    $updates = 0;
    $assignments = [];
    $skipped = [];
    $errors = [];
    $stmtUpdate = $pdo->prepare("UPDATE leads SET desk_id = ?, assigned_to = ?, status = ?, updated_at = NOW() WHERE id = ?");
    foreach ($valid_user_ids as $uid) {
        $countForUser = $distribution[$uid] ?? 0;
        for ($i = 0; $i < $countForUser && $leadIdx < $nLeads; $i++) {
            $leadId = $lead_ids[$leadIdx++];
            if (!in_array($leadId, $existingLeadIds, true)) {
                $skipped[] = ['lead_id' => (int)$leadId, 'reason' => 'not_found'];
                continue;
            }
            $curr = $byLead[$leadId];
            $noChange = ((int)$curr['desk_id'] === (int)$desk_id) && ((int)$curr['assigned_to'] === (int)$uid) && ((string)$curr['status'] === (string)$status);
            if ($noChange) {
                $skipped[] = ['lead_id' => (int)$leadId, 'reason' => 'no_change'];
                continue;
            }
            try {
                $ok = $stmtUpdate->execute([$desk_id, $uid, $status, $leadId]);
                $affected = $ok ? $stmtUpdate->rowCount() : 0;
                if ($affected > 0) {
                    $updates++;
                    $assignments[] = ['lead_id' => (int)$leadId, 'user_id' => (int)$uid];
                    // Registrar historial si el estado cambia
                    if ((string)$curr['status'] !== (string)$status) {
                        $db->execute(
                            "INSERT INTO lead_status_history (lead_id, old_status, new_status, changed_by, notes) VALUES (?, ?, ?, ?, ?)",
                            [$leadId, (string)$curr['status'], (string)$status, $_SESSION['user_id'], 'Asignación masiva']
                        );
                    }
                } else {
                    // Sin filas afectadas (posible valores iguales o restricción)
                    $skipped[] = ['lead_id' => (int)$leadId, 'reason' => 'no_rows_affected'];
                }
            } catch (Exception $ex) {
                $errors[] = ['lead_id' => (int)$leadId, 'error' => $ex->getMessage()];
                // Abortamos y revertimos
                $pdo->rollBack();
                http_response_code(500);
                echo json_encode([
                    'success' => false,
                    'message' => 'Error al asignar uno o más leads',
                    'errors' => $errors,
                    'data' => [
                        'desk_id' => $desk_id,
                        'validated_user_ids' => $valid_user_ids,
                        'invalid_user_ids' => array_values(array_diff($user_ids, $valid_user_ids)),
                        'missing_lead_ids' => $missingLeadIds,
                        'distribution' => $distribution,
                        'skipped' => $skipped
                    ]
                ]);
                return;
            }
        }
    }

    $pdo->commit();

    // Construir mapeo lead -> datos de usuario y desk para actualizar UI
    $lead_updates = [];
    if (!empty($assignments)) {
        $placeU = str_repeat('?,', count($valid_user_ids) - 1) . '?';
        $rowsUsers = $db->select("SELECT id, username, CONCAT(first_name, ' ', last_name) AS full_name FROM users WHERE id IN ($placeU)", $valid_user_ids);
        $nameByUser = [];
        foreach ($rowsUsers as $ru) { $nameByUser[(int)$ru['id']] = trim($ru['full_name']) !== '' ? $ru['full_name'] : $ru['username']; }
        foreach ($assignments as $as) {
            $uid = (int)$as['user_id'];
            $lead_updates[] = [
                'lead_id' => (int)$as['lead_id'],
                'user_id' => $uid,
                'assigned_user_name' => $nameByUser[$uid] ?? ('ID ' . $uid),
                'desk_id' => (int)$desk['id'],
                'desk_name' => (string)$desk['name'],
                'status' => (string)$status
            ];
        }
    }

    echo json_encode([
        'success' => true,
        'message' => 'Leads asignados correctamente',
        'data' => [
            'desk_id' => $desk_id,
            'updated' => $updates,
            'distribution' => $distribution,
            'lead_updates' => $lead_updates,
            // Datos de depuración para entender por qué no se ven cambios
            'validated_user_ids' => $valid_user_ids,
            'invalid_user_ids' => array_values(array_diff($user_ids, $valid_user_ids)),
            'missing_lead_ids' => $missingLeadIds,
            'skipped' => $skipped
        ]
    ]);
} catch (Exception $e) {
    if ($pdo->inTransaction()) { $pdo->rollBack(); }
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => 'Error al asignar leads', 'error' => $e->getMessage()]);
}
?>