<?php
declare(strict_types=1);
require __DIR__.'/lib.php';
if(app_installed()){http_response_code(403);exit('El módulo ya está instalado. Elimine o renombre install.php.');}
$errors=[];$done=false;
if($_SERVER['REQUEST_METHOD']==='POST'){
    $admin=trim((string)($_POST['admin_username']??''));
    $pass=(string)($_POST['admin_password']??'');
    $email=trim((string)($_POST['admin_email']??''));
    $domain=strtolower(trim((string)($_POST['domain']??'uenalbertosmith.com')));
    $webmail=trim((string)($_POST['webmail_url']??''));
    $from=trim((string)($_POST['mail_from']??''));
    $host=trim((string)($_POST['cpanel_host']??''));
    $cpuser=trim((string)($_POST['cpanel_username']??''));
    $token=trim((string)($_POST['cpanel_api_token']??''));
    $driver=(string)($_POST['db_driver']??'sqlite');
    $dbHost=trim((string)($_POST['db_host']??'localhost'));
    $dbName=trim((string)($_POST['db_name']??''));
    $dbUser=trim((string)($_POST['db_username']??''));
    $dbPass=(string)($_POST['db_password']??'');

    if(!extension_loaded('openssl'))$errors[]='El servidor debe habilitar OpenSSL.';
    if(!in_array($driver,['sqlite','mysql'],true))$errors[]='Motor de base de datos no válido.';
    if($driver==='sqlite'&&!extension_loaded('pdo_sqlite'))$errors[]='PDO SQLite no está activo. Seleccione MySQL o habilite PDO SQLite en cPanel.';
    if($driver==='mysql'&&!extension_loaded('pdo_mysql'))$errors[]='PDO MySQL no está activo en la versión de PHP seleccionada.';
    if($driver==='mysql'&&(!$dbHost||!$dbName||!$dbUser))$errors[]='Complete host, base de datos y usuario MySQL.';
    if(!preg_match('/^[a-zA-Z0-9_.-]{4,40}$/',$admin))$errors[]='Usuario administrador no válido.';
    if(strlen($pass)<14||!preg_match('/[A-Z]/',$pass)||!preg_match('/[a-z]/',$pass)||!preg_match('/\d/',$pass)||!preg_match('/[^A-Za-z0-9]/',$pass))$errors[]='La clave administrativa debe tener 14 caracteres e incluir mayúscula, minúscula, número y símbolo.';
    if(!filter_var($email,FILTER_VALIDATE_EMAIL))$errors[]='Correo del administrador no válido.';
    if(!preg_match('/^[a-z0-9.-]+\.[a-z]{2,}$/',$domain))$errors[]='Dominio no válido.';
    if(!filter_var($webmail,FILTER_VALIDATE_URL))$errors[]='URL de Webmail no válida.';
    if(!filter_var($from,FILTER_VALIDATE_EMAIL))$errors[]='Correo remitente no válido.';
    if(($host||$cpuser||$token)&&(!$host||!$cpuser||!$token))$errors[]='Para activar la creación automática debe completar host, usuario y token de cPanel.';
    if(($host&&$cpuser&&$token)&&!extension_loaded('curl'))$errors[]='La extensión PHP cURL debe estar activa para conectar con cPanel.';

    if(!$errors){
        try{
            if(!is_dir(STORAGE_DIR))mkdir(STORAGE_DIR,0700,true);
            $cfg=[
                'domain'=>$domain,'webmail_url'=>$webmail,'mail_from'=>$from,'mail_quota_mb'=>1024,
                'cpanel_host'=>$host,'cpanel_username'=>$cpuser,'cpanel_api_token'=>$token,
                'db_driver'=>$driver,'db_host'=>$dbHost,'db_name'=>$dbName,'db_username'=>$dbUser,'db_password'=>$dbPass,
                'app_key'=>base64_encode(random_bytes(32)),'cedula_pepper'=>bin2hex(random_bytes(32)),
                'otp_pepper'=>bin2hex(random_bytes(32)),'rate_pepper'=>bin2hex(random_bytes(32))
            ];
            $php="<?php\nreturn ".var_export($cfg,true).";\n";
            if(file_put_contents(CONFIG_FILE,$php,LOCK_EX)===false)throw new RuntimeException('No se pudo escribir storage/config.php.');
            chmod(CONFIG_FILE,0600);

            $opts=[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,PDO::ATTR_EMULATE_PREPARES=>false];
            if($driver==='mysql'){
                $pdo=new PDO("mysql:host={$dbHost};dbname={$dbName};charset=utf8mb4",$dbUser,$dbPass,$opts);
                $schema=[
                    "CREATE TABLE IF NOT EXISTS admins (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,username VARCHAR(80) NOT NULL UNIQUE,email_enc TEXT NOT NULL,password_hash VARCHAR(255) NOT NULL,created_at VARCHAR(35) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
                    "CREATE TABLE IF NOT EXISTS teachers (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,cedula_hash CHAR(64) NOT NULL UNIQUE,cedula_last4 VARCHAR(4) NOT NULL,full_name VARCHAR(180) NOT NULL,personal_email_enc TEXT NOT NULL,phone_enc TEXT NULL,status VARCHAR(30) NOT NULL DEFAULT 'authorized',institutional_email VARCHAR(190) NULL,username VARCHAR(80) NULL,totp_secret_enc TEXT NULL,verified_at VARCHAR(35) NULL,created_at VARCHAR(35) NOT NULL,updated_at VARCHAR(35) NOT NULL,INDEX idx_teacher_status(status)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
                    "CREATE TABLE IF NOT EXISTS otp_codes (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,teacher_id BIGINT UNSIGNED NOT NULL,purpose VARCHAR(40) NOT NULL,code_hash CHAR(64) NOT NULL,expires_at VARCHAR(35) NOT NULL,attempts INT NOT NULL DEFAULT 0,used_at VARCHAR(35) NULL,created_at VARCHAR(35) NOT NULL,INDEX idx_otp_teacher(teacher_id,purpose),CONSTRAINT fk_otp_teacher FOREIGN KEY(teacher_id) REFERENCES teachers(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
                    "CREATE TABLE IF NOT EXISTS rate_limits (rate_key VARCHAR(191) PRIMARY KEY,attempts INT NOT NULL,window_start BIGINT NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci",
                    "CREATE TABLE IF NOT EXISTS audit_log (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,event VARCHAR(100) NOT NULL,teacher_id BIGINT UNSIGNED NULL,ip_hash CHAR(64) NOT NULL,metadata TEXT NULL,created_at VARCHAR(35) NOT NULL,INDEX idx_audit_created(created_at),CONSTRAINT fk_audit_teacher FOREIGN KEY(teacher_id) REFERENCES teachers(id) ON DELETE SET NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
                ];
                foreach($schema as $sql)$pdo->exec($sql);
            }else{
                $pdo=new PDO('sqlite:'.DB_FILE,null,null,$opts);
                $pdo->exec("PRAGMA foreign_keys=ON;
                CREATE TABLE admins(id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT UNIQUE NOT NULL,email_enc TEXT NOT NULL,password_hash TEXT NOT NULL,created_at TEXT NOT NULL);
                CREATE TABLE teachers(id INTEGER PRIMARY KEY AUTOINCREMENT,cedula_hash TEXT UNIQUE NOT NULL,cedula_last4 TEXT NOT NULL,full_name TEXT NOT NULL,personal_email_enc TEXT NOT NULL,phone_enc TEXT,status TEXT NOT NULL DEFAULT 'authorized',institutional_email TEXT,username TEXT,totp_secret_enc TEXT,verified_at TEXT,created_at TEXT NOT NULL,updated_at TEXT NOT NULL);
                CREATE TABLE otp_codes(id INTEGER PRIMARY KEY AUTOINCREMENT,teacher_id INTEGER NOT NULL,purpose TEXT NOT NULL,code_hash TEXT NOT NULL,expires_at TEXT NOT NULL,attempts INTEGER NOT NULL DEFAULT 0,used_at TEXT,created_at TEXT NOT NULL,FOREIGN KEY(teacher_id) REFERENCES teachers(id) ON DELETE CASCADE);
                CREATE TABLE rate_limits(rate_key TEXT PRIMARY KEY,attempts INTEGER NOT NULL,window_start INTEGER NOT NULL);
                CREATE TABLE audit_log(id INTEGER PRIMARY KEY AUTOINCREMENT,event TEXT NOT NULL,teacher_id INTEGER,ip_hash TEXT NOT NULL,metadata TEXT,created_at TEXT NOT NULL,FOREIGN KEY(teacher_id) REFERENCES teachers(id) ON DELETE SET NULL);
                CREATE INDEX idx_otp_teacher ON otp_codes(teacher_id,purpose);CREATE INDEX idx_audit_created ON audit_log(created_at);");
                chmod(DB_FILE,0600);
            }

            $iv=random_bytes(12);$tag='';
            $cipher=openssl_encrypt(strtolower($email),'aes-256-gcm',substr(base64_decode($cfg['app_key']),0,32),OPENSSL_RAW_DATA,$iv,$tag,'uen-correo');
            if($cipher===false)throw new RuntimeException('No se pudo cifrar el correo del administrador.');
            $emailEnc=base64_encode($iv.$tag.$cipher);
            $st=$pdo->prepare('INSERT INTO admins(username,email_enc,password_hash,created_at) VALUES(?,?,?,?)');
            $st->execute([$admin,$emailEnc,password_hash($pass,PASSWORD_DEFAULT),date('c')]);
            file_put_contents(INSTALL_LOCK,date('c'),LOCK_EX);chmod(INSTALL_LOCK,0600);$done=true;
        }catch(Throwable $e){
            @unlink(INSTALL_LOCK);@unlink(CONFIG_FILE);if($driver==='sqlite')@unlink(DB_FILE);
            $errors[]='No se pudo completar la instalación: '.$e->getMessage();
        }
    }
}
?><!doctype html><html lang="es"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Instalar registro de correo docente</title><link rel="stylesheet" href="../assets/css/styles.css"><link rel="stylesheet" href="styles.css"></head><body class="mail-app"><main class="mail-shell"><div class="mail-brand"><img src="../assets/img/logo.png" alt=""><div><b>U.E.N. Alberto Smith</b><span>Instalación del registro docente</span></div></div><?php if($done):?><div class="mail-panel"><h1>Instalación completada</h1><div class="alert success">El módulo quedó instalado. Por seguridad, elimine o renombre <code>correo-docente/install.php</code>.</div><p><a class="btn btn-red" href="admin.php">Abrir administración</a> <a class="btn btn-outline-dark" href="index.php">Ver registro docente</a></p></div><?php else:?><div class="mail-panel"><h1>Configuración inicial</h1><p>Esta instalación crea la base de datos, el administrador y la conexión opcional con la API de cPanel.</p><?php foreach($errors as $e):?><div class="alert error"><?=h($e)?></div><?php endforeach;?><form method="post" class="mail-form"><h2>Administrador</h2><div class="form-two"><label>Usuario<input name="admin_username" required autocomplete="username" value="<?=h((string)($_POST['admin_username']??''))?>"></label><label>Correo personal del administrador<input type="email" name="admin_email" required value="<?=h((string)($_POST['admin_email']??''))?>"></label></div><label>Contraseña administrativa<input type="password" name="admin_password" required autocomplete="new-password"><small>Mínimo 14 caracteres, mayúscula, minúscula, número y símbolo.</small></label><h2>Base de datos</h2><label>Motor<select name="db_driver" id="dbDriver"><option value="sqlite" <?=($_POST['db_driver']??'sqlite')==='sqlite'?'selected':''?>>SQLite — instalación sencilla</option><option value="mysql" <?=($_POST['db_driver']??'')==='mysql'?'selected':''?>>MySQL/MariaDB — recomendado en cPanel</option></select></label><div id="mysqlFields"><div class="form-two"><label>Host MySQL<input name="db_host" value="<?=h((string)($_POST['db_host']??'localhost'))?>"></label><label>Nombre de base de datos<input name="db_name" value="<?=h((string)($_POST['db_name']??''))?>"></label></div><div class="form-two"><label>Usuario MySQL<input name="db_username" value="<?=h((string)($_POST['db_username']??''))?>"></label><label>Contraseña MySQL<input type="password" name="db_password" autocomplete="new-password"></label></div><small>En cPanel cree primero la base y el usuario en “Bases de datos MySQL” y asígnele todos los privilegios.</small></div><h2>Correo institucional</h2><div class="form-two"><label>Dominio<input name="domain" value="<?=h((string)($_POST['domain']??'uenalbertosmith.com'))?>" required></label><label>Webmail seguro<input type="url" name="webmail_url" value="<?=h((string)($_POST['webmail_url']??'https://uenalbertosmith.com:2096/'))?>" required></label></div><label>Remitente para códigos OTP<input type="email" name="mail_from" value="<?=h((string)($_POST['mail_from']??'no-reply@uenalbertosmith.com'))?>" required></label><h2>API de cPanel <small>(opcional durante la instalación)</small></h2><p class="muted">Sin estos datos, el sistema podrá autorizar docentes, pero no crear automáticamente el buzón. Puede completar después <code>storage/config.php</code>.</p><label>Host cPanel<input type="url" name="cpanel_host" placeholder="https://servidor.ejemplo.com:2083" value="<?=h((string)($_POST['cpanel_host']??''))?>"></label><div class="form-two"><label>Usuario cPanel<input name="cpanel_username" autocomplete="off" value="<?=h((string)($_POST['cpanel_username']??''))?>"></label><label>Token API cPanel<input type="password" name="cpanel_api_token" autocomplete="new-password"></label></div><button class="btn btn-red" type="submit">Instalar módulo</button></form></div><script>const d=document.getElementById('dbDriver'),m=document.getElementById('mysqlFields');function sync(){m.style.display=d.value==='mysql'?'grid':'none'}d.addEventListener('change',sync);sync();</script><?php endif;?></main></body></html>
