<?php

class SyncController
{
    private PDO $pdo;
    private SicService $sic;

    public function __construct()
    {
        $db = new Database();
        $this->pdo = $db->connect();
        $this->sic = new SicService();
    }

    public function syncPeliculas(): void
    {
        $modulo = 'produccion_cine';

        $totalPeliculas = 0;
        $totalImagenes = 0;

        try {
            $this->pdo->beginTransaction();

            $peliculas = $this->sic->getRecords($modulo);
            $imagenes = $this->sic->getImages($modulo);

            foreach ($peliculas as $item) {
                $this->guardarPelicula($item);
                $totalPeliculas++;
            }

            foreach ($imagenes as $img) {
                if (($img['tabla_nombre'] ?? '') !== 'produccion_cine') {
                    continue;
                }

                $this->guardarImagen($img);
                $totalImagenes++;
            }

            $this->guardarLog($modulo, $totalPeliculas, $totalImagenes, 'ok', 'Sincronización completada correctamente');

            $this->pdo->commit();

            jsonResponse([
                'success' => true,
                'message' => 'Sincronización completada correctamente',
                'total_peliculas' => $totalPeliculas,
                'total_imagenes' => $totalImagenes
            ]);

        } catch (Exception $e) {
            $this->pdo->rollBack();

            $this->guardarLog($modulo, $totalPeliculas, $totalImagenes, 'error', $e->getMessage());

            jsonResponse([
                'success' => false,
                'message' => 'Error al sincronizar películas',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    private function guardarPelicula(array $item): void
    {
        $sicId = $this->value($item, ['produccion_cine_id']);

        if (!$sicId) {
            return;
        }

        $director = trim(
            ($this->value($item, ['produccion_cine_director_nom']) ?? '') . ' ' .
            ($this->value($item, ['produccion_cine_director_ap']) ?? '') . ' ' .
            ($this->value($item, ['produccion_cine_director_am']) ?? '')
        );

        if ($director === '') {
            $director = $this->value($item, [
                'produccion_cine_director',
                'director',
                'direccion'
            ]);
        }

        $contacto = $this->armarContacto($item);

        $sql = "
            INSERT INTO peliculas (
                sic_id,
                serial_renic,
                info_publica,
                titulo_original,
                titulo_espanol,
                titulo_ingles,
                pais,
                anio,
                duracion,
                tipo_produccion,
                genero,
                idioma,
                locacion,
                direccion,
                produccion,
                guion,
                cinematografia,
                edicion,
                sonido,
                musica,
                direccion_arte,
                animacion,
                reparto,
                compania_productora,
                apoyos,
                sinopsis_espanol,
                sinopsis_ingles,
                contacto,
                raw_json,
                fecha_sincronizacion
            ) VALUES (
                :sic_id,
                :serial_renic,
                :info_publica,
                :titulo_original,
                :titulo_espanol,
                :titulo_ingles,
                :pais,
                :anio,
                :duracion,
                :tipo_produccion,
                :genero,
                :idioma,
                :locacion,
                :direccion,
                :produccion,
                :guion,
                :cinematografia,
                :edicion,
                :sonido,
                :musica,
                :direccion_arte,
                :animacion,
                :reparto,
                :compania_productora,
                :apoyos,
                :sinopsis_espanol,
                :sinopsis_ingles,
                :contacto,
                :raw_json,
                NOW()
            )
            ON DUPLICATE KEY UPDATE
                serial_renic = VALUES(serial_renic),
                info_publica = VALUES(info_publica),
                titulo_original = VALUES(titulo_original),
                titulo_espanol = VALUES(titulo_espanol),
                titulo_ingles = VALUES(titulo_ingles),
                pais = VALUES(pais),
                anio = VALUES(anio),
                duracion = VALUES(duracion),
                tipo_produccion = VALUES(tipo_produccion),
                genero = VALUES(genero),
                idioma = VALUES(idioma),
                locacion = VALUES(locacion),
                direccion = VALUES(direccion),
                produccion = VALUES(produccion),
                guion = VALUES(guion),
                cinematografia = VALUES(cinematografia),
                edicion = VALUES(edicion),
                sonido = VALUES(sonido),
                musica = VALUES(musica),
                direccion_arte = VALUES(direccion_arte),
                animacion = VALUES(animacion),
                reparto = VALUES(reparto),
                compania_productora = VALUES(compania_productora),
                apoyos = VALUES(apoyos),
                sinopsis_espanol = VALUES(sinopsis_espanol),
                sinopsis_ingles = VALUES(sinopsis_ingles),
                contacto = VALUES(contacto),
                raw_json = VALUES(raw_json),
                fecha_sincronizacion = NOW()
        ";

        $stmt = $this->pdo->prepare($sql);

        $stmt->execute([
            ':sic_id' => (int)$sicId,
            ':serial_renic' => $this->value($item, ['serial_renic']),
            ':info_publica' => $this->boolToInt($this->value($item, ['produccion_cine_info_publica', 'info_publica'])),

            ':titulo_original' => $this->value($item, [
                'produccion_cine_nombre_original',
                'produccion_cine_nombre'
            ]),
            ':titulo_espanol' => $this->value($item, [
                'produccion_cine_nombre',
                'titulo_espanol'
            ]),
            ':titulo_ingles' => $this->value($item, [
                'produccion_cine_nombre_ing',
                'produccion_cine_nombre_en'
            ]),

            ':pais' => $this->value($item, ['produccion_cine_pais']),
            ':anio' => $this->validYear($this->value($item, [
                'produccion_cine_anio',
                'produccion_cine_anno',
                'produccion_cine_año'
            ])),
            ':duracion' => $this->value($item, [
                'produccion_cine_duracion',
                'produccion_cine_duracion2'
            ]),
            ':tipo_produccion' => $this->value($item, ['produccion_cine_tipo']),
            ':genero' => $this->value($item, ['produccion_cine_genero', 'genero']),
            ':idioma' => $this->value($item, [
                'produccion_cine_idioma',
                'produccion_cine_lengua',
                'idioma'
            ]),
            ':locacion' => $this->value($item, ['produccion_cine_locacion', 'locacion']),

            ':direccion' => $director,
            ':produccion' => $this->value($item, [
                'produccion_cine_productor',
                'produccion_cine_produccion',
                'produccion'
            ]),
            ':guion' => $this->value($item, ['produccion_cine_guion']),
            ':cinematografia' => $this->value($item, [
                'produccion_cine_fotografia',
                'produccion_cine_cinematografia'
            ]),
            ':edicion' => $this->value($item, ['produccion_cine_edicion']),
            ':sonido' => $this->value($item, ['produccion_cine_sonido']),
            ':musica' => $this->value($item, ['produccion_cine_musica']),
            ':direccion_arte' => $this->value($item, ['produccion_cine_direccion_arte']),
            ':animacion' => $this->limitarPersonas($this->value($item, [
                'produccion_cine_animacion',
                'animacion'
            ]), 8),
            
            ':reparto' => $this->limitarPersonas($this->limpiarHtml($this->value($item, [
                'produccion_cine_reparto',
                'reparto'
            ])), 8),

            ':compania_productora' => $this->value($item, [
                'produccion_cine_compania',
                'produccion_cine_compania2',
                'produccion_cine_compannia',
                'produccion_cine_compannia2',
                'compania_productora'
            ]),
            ':apoyos' => $this->limpiarHtml($this->value($item, [
                'produccion_cine_apoyos',
                'produccion_cine_fideicomiso',
                'apoyos',
                'film_fundings'
            ])),

            ':sinopsis_espanol' => $this->limpiarHtml($this->value($item, [
                'produccion_cine_sinopsis',
                'produccion_cine_sipnosis',
                'produccion_cine_resumen',
                'produccion_cine_descripcion',
                'sinopsis',
                'sipnosis',
                'sinopsis_espanol'
            ])),

            ':sinopsis_ingles' => $this->limpiarHtml($this->value($item, [
                'produccion_cine_sinopsis_ing',
                'produccion_cine_sipnosis_ing',
                'produccion_cine_sinopsis_en',
                'produccion_cine_sipnosis_en',
                'produccion_cine_resumen_ing',
                'produccion_cine_resumen_en',
                'sinopsis_ing',
                'sipnosis_ing',
                'sinopsis_ingles'
            ])),
            ':contacto' => $contacto,

            ':raw_json' => json_encode($item, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
        ]);
    }

    private function guardarImagen(array $img): void
    {
        $peliculaSicId = $this->value($img, ['tabla_id']);

        if (!$peliculaSicId || empty($img['url'])) {
            return;
        }

        $peliculaId = $this->buscarPeliculaIdPorSicId((int)$peliculaSicId);

        $sql = "
            INSERT INTO peliculas_imagenes (
                pelicula_id,
                pelicula_sic_id,
                imagen_id,
                url,
                tipo,
                pie,
                descripcion,
                autor,
                fecha_incorporacion,
                raw_json,
                fecha_sincronizacion
            ) VALUES (
                :pelicula_id,
                :pelicula_sic_id,
                :imagen_id,
                :url,
                :tipo,
                :pie,
                :descripcion,
                :autor,
                :fecha_incorporacion,
                :raw_json,
                NOW()
            )
            ON DUPLICATE KEY UPDATE
                pelicula_id = VALUES(pelicula_id),
                url = VALUES(url),
                tipo = VALUES(tipo),
                pie = VALUES(pie),
                descripcion = VALUES(descripcion),
                autor = VALUES(autor),
                fecha_incorporacion = VALUES(fecha_incorporacion),
                raw_json = VALUES(raw_json),
                fecha_sincronizacion = NOW()
        ";

        $stmt = $this->pdo->prepare($sql);

        $stmt->execute([
            ':pelicula_id' => $peliculaId,
            ':pelicula_sic_id' => (int)$peliculaSicId,
            ':imagen_id' => $this->value($img, ['imagen_id']),
            ':url' => $img['url'],
            ':tipo' => $this->value($img, ['tipo']),
            ':pie' => $this->value($img, ['pie']),
            ':descripcion' => $this->value($img, ['des']),
            ':autor' => $this->value($img, ['autor']),
            ':fecha_incorporacion' => $this->formatDate($this->value($img, ['fhi'])),
            ':raw_json' => json_encode($img, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
        ]);
    }

    private function buscarPeliculaIdPorSicId(int $sicId): ?int
    {
        $stmt = $this->pdo->prepare("SELECT id FROM peliculas WHERE sic_id = :sic_id LIMIT 1");
        $stmt->execute([':sic_id' => $sicId]);
        $row = $stmt->fetch();

        return $row ? (int)$row['id'] : null;
    }

    private function guardarLog(string $modulo, int $totalRegistros, int $totalImagenes, string $estatus, string $mensaje): void
    {
        try {
            $stmt = $this->pdo->prepare("
                INSERT INTO sync_logs (
                    modulo,
                    total_registros,
                    total_imagenes,
                    estatus,
                    mensaje
                ) VALUES (
                    :modulo,
                    :total_registros,
                    :total_imagenes,
                    :estatus,
                    :mensaje
                )
            ");

            $stmt->execute([
                ':modulo' => $modulo,
                ':total_registros' => $totalRegistros,
                ':total_imagenes' => $totalImagenes,
                ':estatus' => $estatus,
                ':mensaje' => $mensaje
            ]);
        } catch (Exception $e) {
            // Evita que falle toda la sincronización solo por el log
        }
    }

    private function value(array $item, array $keys): mixed
    {
        foreach ($keys as $key) {
            if (array_key_exists($key, $item) && $item[$key] !== '' && $item[$key] !== null) {
                return $item[$key];
            }
        }

        return null;
    }

    private function boolToInt(mixed $value): int
    {
        if ($value === true || $value === 1 || $value === '1' || $value === 'true') {
            return 1;
        }

        return 0;
    }

    private function validYear(mixed $value): ?int
    {
        if (!$value) {
            return null;
        }

        $year = (int)$value;

        if ($year < 1800 || $year > 2100) {
            return null;
        }

        return $year;
    }

    private function formatDate(?string $date): ?string
    {
        if (!$date) {
            return null;
        }

        $date = str_replace('T', ' ', $date);

        if (strlen($date) > 19) {
            $date = substr($date, 0, 19);
        }

        return $date;
    }

    private function limpiarHtml(?string $text): ?string
    {
        if (!$text) {
            return null;
        }

        $text = str_replace(['<br>', '<br/>', '<br />'], "\n", $text);
        $text = strip_tags($text);
        $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');

        return trim($text);
    }

    private function limitarPersonas(?string $text, int $limite): ?string
    {
        if (!$text) {
            return null;
        }

        $text = trim($text);

        $personas = preg_split('/,|;|\n|\r/', $text);
        $personas = array_map('trim', $personas);
        $personas = array_filter($personas);

        if (count($personas) === 0) {
            return $text;
        }

        $personas = array_slice($personas, 0, $limite);

        return implode(', ', $personas);
    }

    private function armarContacto(array $item): ?string
    {
        $partes = [];

        $campos = [
            'produccion_cine_contacto',
            'email',
            'email2',
            'pagina_web',
            'pagina_web2',
            'produccion_cine_telefono1',
            'produccion_cine_telefono2'
        ];

        foreach ($campos as $campo) {
            if (!empty($item[$campo])) {
                $partes[] = $item[$campo];
            }
        }

        if (empty($partes)) {
            return null;
        }

        return implode("\n", $partes);
    }
}