<?php

namespace App\Models;

use CodeIgniter\Model;

class AsientoModel extends Model
{
    protected $table            = 'asiento';
    protected $primaryKey       = 'id_asiento';
    protected $useAutoIncrement = true;
    protected $returnType       = 'App\Entities\Asiento';
    protected $useSoftDeletes   = false;
    protected $protectFields    = true;
    protected $allowedFields    = [
        'id_sala',
        'fila',
        'numero',
        'tipo'
    ];

    protected $validationRules = [
        'id_sala' => 'required|integer',
        'fila'    => 'required|max_length[2]',
        'numero'  => 'required|integer|greater_than[0]',
        'tipo'    => 'required|in_list[estandar,preferencial,discapacitado]',
    ];

    /**
     * Obtiene los asientos de una sala cruzados con la ocupación de una función específica.
     */
    public function getAsientosConOcupacion(int $id_funcion, int $id_sala)
    {
        return $this->select('asiento.*, 
                CASE WHEN dr.id_asiento IS NOT NULL THEN \'ocupado\' ELSE \'disponible\' END AS estado_ocupacion')
            ->join('detalle_reserva dr', 'dr.id_asiento = asiento.id_asiento AND dr.id_funcion = ' . $id_funcion, 'left')
            ->where('asiento.id_sala', $id_sala)
            ->orderBy('asiento.fila', 'ASC')
            ->orderBy('asiento.numero', 'ASC')
            ->findAll();
    }

    /**
     * Genera automáticamente el mapa de butacas (filas x columnas) para una sala,
     * en base a su capacidad. Se usa al crear una sala nueva desde el panel admin,
     * ya que antes las salas se creaban sin ningún asiento y las funciones asignadas
     * a ellas quedaban sin butacas seleccionables.
     *
     * Es idempotente por seguridad: si la sala ya tiene asientos, no hace nada,
     * salvo que se pase $forzar = true.
     *
     * @return int Cantidad de asientos generados (0 si no se generó nada).
     */
    public function generarAsientosParaSala(int $id_sala, int $capacidad, bool $forzar = false): int
    {
        if ($capacidad <= 0) {
            return 0;
        }

        $existentes = $this->where('id_sala', $id_sala)->countAllResults();
        if ($existentes > 0 && !$forzar) {
            return 0;
        }

        if ($forzar && $existentes > 0) {
            $this->where('id_sala', $id_sala)->delete();
        }

        // Máximo de asientos por fila (patrón similar al de los datos de ejemplo).
        $columnas = 10;
        $totalFilas = (int) ceil($capacidad / $columnas);
        $totalFilas = max(1, $totalFilas);

        // Letras de fila: A, B, C ... Z, AA, AB, ...
        $letras = [];
        for ($i = 0; $i < $totalFilas; $i++) {
            $letras[] = $this->numeroALetraFila($i);
        }

        // Filas "preferenciales" (un poco más cómodas): un tercio central de las filas.
        $inicioPreferencial = (int) floor($totalFilas * 0.35);
        $finPreferencial    = (int) ceil($totalFilas * 0.75);

        // Fila reservada para asientos accesibles (discapacitado): cercana a la pantalla
        // pero no la primerísima fila, para facilitar el acceso.
        $filaAccesible = $totalFilas >= 3 ? 1 : -1;

        $asientosPorInsertar = [];
        $restante = $capacidad;

        for ($f = 0; $f < $totalFilas; $f++) {
            $asientosEnFila = min($columnas, $restante);
            if ($asientosEnFila <= 0) {
                break;
            }

            $mitad = (int) floor($asientosEnFila / 2);

            for ($n = 1; $n <= $asientosEnFila; $n++) {
                $tipo = 'estandar';
                $esCentral = $n === $mitad || $n === $mitad + 1;

                if ($f === $filaAccesible && $esCentral && $asientosEnFila >= 4) {
                    $tipo = 'discapacitado';
                } elseif ($f >= $inicioPreferencial && $f < $finPreferencial && $esCentral && $asientosEnFila >= 4) {
                    $tipo = 'preferencial';
                }

                $asientosPorInsertar[] = [
                    'id_sala' => $id_sala,
                    'fila'    => $letras[$f],
                    'numero'  => $n,
                    'tipo'    => $tipo,
                ];
            }

            $restante -= $asientosEnFila;
        }

        if (empty($asientosPorInsertar)) {
            return 0;
        }

        $this->insertBatch($asientosPorInsertar);

        return count($asientosPorInsertar);
    }

    /**
     * Convierte un índice numérico (0, 1, 2...) en una letra de fila (A, B, C... Z, AA, AB...).
     */
    private function numeroALetraFila(int $indice): string
    {
        $letra = '';
        $indice++; // 1-indexado para el algoritmo tipo columnas de Excel

        while ($indice > 0) {
            $resto = ($indice - 1) % 26;
            $letra = chr(65 + $resto) . $letra;
            $indice = (int) (($indice - $resto) / 26);
        }

        return $letra;
    }
}
