<?php

declare(strict_types=1);

/**
 * Script de inicialización y seeding de la base de datos.
 * Ejecutar con: php bin/db-init.php
 */

require_once dirname(__DIR__) . '/config/bootstrap.php';

use ApiModel\Infrastructure\Persistence\Database;
use ApiModel\Infrastructure\Persistence\Repositories\PdoUserRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoRoleRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoModuleRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoPageRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoProfileRepository;
use ApiModel\Infrastructure\Persistence\Repositories\PdoMessageRepository;

echo "=== INICIALIZACIÓN DE BASE DE DATOS CONTABLE ===\n";

try {
    $pdo = Database::connect();
    echo "Conectado a la base de datos con éxito.\n";

    // 1. Cargar DDL
    $ddlPath = dirname(__DIR__) . '/docs/db_schema_auth.sql';
    if (!file_exists($ddlPath)) {
        throw new RuntimeException("No se encontró el archivo DDL en: {$ddlPath}");
    }

    echo "Ejecutando DDL desde docs/db_schema_auth.sql...\n";
    $ddl = file_get_contents($ddlPath);
    
    // SQLite no soporta CREATE SCHEMA ni gen_random_uuid() de PostgreSQL,
    // adaptamos el DDL si la conexión es SQLite
    $driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
    if ($driver === 'sqlite') {
        echo "Adaptando esquema para SQLite...\n";
        // Eliminar esquema
        $ddl = str_replace('CREATE SCHEMA IF NOT EXISTS auth;', '', $ddl);
        $ddl = str_replace('auth.', '', $ddl); // Quitar prefijo de esquema
        $ddl = str_replace('DEFAULT gen_random_uuid()', '', $ddl);
        $ddl = str_replace('SERIAL PRIMARY KEY', 'INTEGER PRIMARY KEY AUTOINCREMENT', $ddl);
        $ddl = str_replace('JSONB', 'TEXT', $ddl);
    }

    $pdo->exec($ddl);
    echo "Tablas creadas/actualizadas con éxito.\n";

    // 2. Seeding
    echo "Insertando datos de semilla (Seeding)...\n";

    $userRepo = new PdoUserRepository($pdo);
    $roleRepo = new PdoRoleRepository($pdo);
    $modRepo = new PdoModuleRepository($pdo);
    $pageRepo = new PdoPageRepository($pdo);
    $profileRepo = new PdoProfileRepository($pdo);
    $msgRepo = new PdoMessageRepository($pdo);

    // Roles
    $adminRoleId = Database::uuid();
    $managerRoleId = Database::uuid();
    $clientRoleId = Database::uuid();

    echo "Creando roles básicos...\n";
    $roleRepo->insert($adminRoleId, 'Administrador', 'Administrator', 'Control total de la plataforma', 'Full platform control');
    $roleRepo->insert($managerRoleId, 'Gerente', 'Manager', 'Acceso a operaciones contables y de negocio', 'Business and accounting operations');
    $roleRepo->insert($clientRoleId, 'Cliente', 'Client', 'Acceso para clientes externos', 'External client access');

    // Módulos
    $modConfigId = Database::uuid();
    $modAcctId = Database::uuid();

    echo "Creando módulos del menú...\n";
    $modRepo->insert($modConfigId, 'Configuración', 'Configuration', 'settings', 10);
    $modRepo->insert($modAcctId, 'Contabilidad', 'Accounting', 'account_balance', 20);

    // Páginas
    $pageUsersId = Database::uuid();
    $pageRolesId = Database::uuid();
    $pageMsgId = Database::uuid();
    $pageChartId = Database::uuid();
    $pageJourId = Database::uuid();

    echo "Creando páginas de menú...\n";
    $pageRepo->insert($pageUsersId, $modConfigId, 'Usuarios', 'Users', '/security/users', 'people', 1);
    $pageRepo->insert($pageRolesId, $modConfigId, 'Roles y Permisos', 'Roles & Permissions', '/security/roles', 'security', 2);
    $pageRepo->insert($pageMsgId, $modConfigId, 'Plantillas de Correo', 'Email Templates', '/security/messages', 'email', 3);
    $pageRepo->insert($pageChartId, $modAcctId, 'Plan de Cuentas', 'Chart of Accounts', '/accounting/chart', 'account_tree', 1);
    $pageRepo->insert($pageJourId, $modAcctId, 'Asientos Contables', 'Journal Entries', '/accounting/journals', 'history_edu', 2);

    // Configurar perfiles para el rol Administrador (Acceso total)
    echo "Configurando perfil del administrador...\n";
    $profileRepo->savePermission($adminRoleId, $pageUsersId, true, true, true, true);
    $profileRepo->savePermission($adminRoleId, $pageRolesId, true, true, true, true);
    $profileRepo->savePermission($adminRoleId, $pageMsgId, true, true, true, true);
    $profileRepo->savePermission($adminRoleId, $pageChartId, true, true, true, true);
    $profileRepo->savePermission($adminRoleId, $pageJourId, true, true, true, true);

    // Configurar perfiles para el rol Gerente (Acceso contabilidad y lectura de configuración de usuarios)
    echo "Configurando perfil del gerente...\n";
    $profileRepo->savePermission($managerRoleId, $pageUsersId, true, false, false, false);
    $profileRepo->savePermission($managerRoleId, $pageChartId, true, true, true, true);
    $profileRepo->savePermission($managerRoleId, $pageJourId, true, true, true, true);

    // Crear Plantilla de recuperación de contraseña
    echo "Creando plantilla de correo para recuperación de clave...\n";
    $msgRepo->insert(
        Database::uuid(),
        'PASSWORD_RESET',
        'Código de recuperación de contraseña',
        'Password Reset Code',
        '<div style="font-family: Arial, sans-serif; padding: 20px;">
            <h2>Recuperación de Contraseña</h2>
            <p>Hemos recibido una solicitud para restablecer tu contraseña.</p>
            <p>Usa el siguiente código de seguridad de 6 dígitos:</p>
            <h3 style="color: #1976D2; font-size: 24px; letter-spacing: 2px;">{{code}}</h3>
            <p>Este código expira en 15 minutos. Si no realizaste esta solicitud, puedes ignorar este correo de forma segura.</p>
         </div>',
        '<div style="font-family: Arial, sans-serif; padding: 20px;">
            <h2>Password Recovery</h2>
            <p>We received a request to reset your password.</p>
            <p>Use the following 6-digit security code:</p>
            <h3 style="color: #1976D2; font-size: 24px; letter-spacing: 2px;">{{code}}</h3>
            <p>This code expires in 15 minutes. If you did not request this, you can safely ignore this email.</p>
         </div>'
    );

    // Crear usuario admin principal si no existe
    echo "Creando usuario administrador de prueba (admin@example.com / Secret123!)...\n";
    $adminEmail = 'admin@example.com';
    if (!$userRepo->emailExists($adminEmail)) {
        $adminUserId = Database::uuid();
        $hash = password_hash('Secret123!', PASSWORD_BCRYPT, ['cost' => 10]);
        $userRepo->insertUserWithPassword($adminUserId, 'Admin Contable', $adminEmail, $hash, 'ADMINISTRADOR', 'es');
        
        // El repositorio vincula automáticamente por nombre de rol, pero aseguramos vinculación al rol creado
        // eliminando roles vinculados por defecto e insertando el id correcto
        $pdo->prepare('DELETE FROM role_user WHERE user_id = ?')->execute([$adminUserId]);
        $pdo->prepare('INSERT INTO role_user (role_id, user_id) VALUES (?,?)')->execute([$adminRoleId, $adminUserId]);
        
        echo "Usuario administrador creado y vinculado al rol de forma relacional.\n";
    } else {
        echo "El usuario administrador ya existe.\n";
    }

    echo "=== PROCESO DE INICIALIZACIÓN COMPLETADO CON ÉXITO ===\n";

} catch (Exception $e) {
    echo "ERROR: Ocurrió un fallo durante la inicialización: " . $e->getMessage() . "\n";
    exit(1);
}
