<?php
/**
 * Modelo Sorteos — Sprint 16S
 * Soporta fuente: 'quorum' (quorum=1) | 'todos' (activo=1)
 * Soporta filtro horario por TIME(fecha_ingreso)
 */
class Sorteos {

    private $db;

    public function __construct() {
        require_once 'conexion.php';
        $this->db = (new \app\models\conexion())->DB();
    }

    /**
     * Construye cláusula WHERE + parámetros según fuente y filtro horario.
     * Retorna [$whereClause, $params]
     */
    private function buildWhereParams(string $fuente, string $horaDesde, string $horaHasta): array {
        $where  = $fuente === 'todos' ? 'activo = 1' : 'quorum = 1';
        $params = [];
        if ($fuente !== 'todos' && $horaDesde !== '' && $horaHasta !== '') {
            $where .= " AND TIME(fecha_ingreso) BETWEEN :hd AND :hh";
            $params = [':hd' => $horaDesde, ':hh' => $horaHasta];
        }
        return [$where, $params];
    }

    /**
     * Crea un nuevo sorteo con nombre de regalo y cantidad de ganadores.
     */
    public function crearSorteo(string $regalo, int $cantidad): int {
        $stmt = $this->db->prepare(
            "INSERT INTO sorteos (nombre_regalo, cantidad_ganadores, estado)
             VALUES (:regalo, :cantidad, 'pendiente')"
        );
        $stmt->execute([':regalo' => $regalo, ':cantidad' => $cantidad]);
        return (int)$this->db->lastInsertId();
    }

    /**
     * Ejecuta el sorteo seleccionando N delegados aleatorios del pool configurado.
     * Excluye ganadores de sorteos anteriores de la misma sesión.
     */
    public function ejecutarSorteo(int $sorteoId, string $fuente = 'quorum', string $horaDesde = '', string $horaHasta = ''): array|false {
        $stmt = $this->db->prepare("SELECT * FROM sorteos WHERE id = :id");
        $stmt->execute([':id' => $sorteoId]);
        $sorteo = $stmt->fetch(PDO::FETCH_OBJ);
        if (!$sorteo) return false;

        // IDs de ganadores previos — excluir del pool
        $previos = $this->db->query(
            "SELECT DISTINCT user_id FROM sorteo_ganadores"
        )->fetchAll(PDO::FETCH_COLUMN);

        $excludeList = !empty($previos)
            ? 'AND u.user_id NOT IN (' . implode(',', array_map('intval', $previos)) . ')'
            : '';

        [$where, $timeParams] = $this->buildWhereParams($fuente, $horaDesde, $horaHasta);

        $stmt = $this->db->prepare(
            "SELECT u.user_id, u.name, u.username AS cedula, u.zona
             FROM users u
             WHERE $where
             $excludeList
             ORDER BY RAND()
             LIMIT :cantidad"
        );
        $stmt->bindValue(':cantidad', (int)$sorteo->cantidad_ganadores, PDO::PARAM_INT);
        foreach ($timeParams as $k => $v) {
            $stmt->bindValue($k, $v);
        }
        $stmt->execute();
        $ganadores = $stmt->fetchAll(PDO::FETCH_OBJ);

        if (empty($ganadores)) return false;

        // Registrar en transacción atómica
        $this->db->beginTransaction();
        try {
            foreach ($ganadores as $g) {
                $ins = $this->db->prepare(
                    "INSERT INTO sorteo_ganadores (sorteo_id, user_id, nombre, cedula, zona, regalo)
                     VALUES (:sid, :uid, :nombre, :cedula, :zona, :regalo)"
                );
                $ins->execute([
                    ':sid'    => $sorteoId,
                    ':uid'    => $g->user_id,
                    ':nombre' => $g->name,
                    ':cedula' => $g->cedula,
                    ':zona'   => $g->zona,
                    ':regalo' => $sorteo->nombre_regalo,
                ]);
            }
            $this->db->prepare(
                "UPDATE sorteos SET estado = 'ejecutado' WHERE id = :id"
            )->execute([':id' => $sorteoId]);
            $this->db->commit();
        } catch (Exception $e) {
            $this->db->rollBack();
            return false;
        }

        return $ganadores;
    }

    /**
     * Lista todos los ganadores registrados (UI e historial/CSV).
     */
    public function ganadores(): array {
        return $this->db->query(
            "SELECT sg.nombre, sg.cedula, sg.zona, sg.regalo, sg.fecha,
                    s.nombre_regalo, s.cantidad_ganadores
             FROM sorteo_ganadores sg
             JOIN sorteos s ON s.id = sg.sorteo_id
             ORDER BY sg.fecha ASC"
        )->fetchAll(PDO::FETCH_OBJ);
    }

    /**
     * Total de participantes disponibles según fuente y filtro horario.
     * Excluye ganadores previos.
     */
    public function disponiblesParaSorteo(string $fuente = 'quorum', string $horaDesde = '', string $horaHasta = ''): int {
        $previos = (int)$this->db->query(
            "SELECT COUNT(DISTINCT user_id) FROM sorteo_ganadores"
        )->fetchColumn();

        [$where, $timeParams] = $this->buildWhereParams($fuente, $horaDesde, $horaHasta);
        $stmt = $this->db->prepare("SELECT COUNT(*) FROM users WHERE $where");
        $stmt->execute($timeParams);
        $total = (int)$stmt->fetchColumn();

        return max(0, $total - $previos);
    }

    /**
     * Lista de todos los sorteos del día.
     */
    public function listarSorteos(): array {
        return $this->db->query(
            "SELECT s.*, COUNT(sg.id) as total_ganadores
             FROM sorteos s
             LEFT JOIN sorteo_ganadores sg ON sg.sorteo_id = s.id
             GROUP BY s.id
             ORDER BY s.fecha_sorteo DESC"
        )->fetchAll(PDO::FETCH_OBJ);
    }

    /**
     * Resetea ganadores y sorteos (solo para reset pre-asamblea).
     */
    public function resetear(): void {
        $this->db->exec("SET FOREIGN_KEY_CHECKS = 0");
        $this->db->exec("TRUNCATE TABLE sorteo_ganadores");
        $this->db->exec("TRUNCATE TABLE sorteos");
        $this->db->exec("SET FOREIGN_KEY_CHECKS = 1");
    }
}
