<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Database;
use App\Core\Request;
use App\Core\Session;
use App\Core\Tenant;
use App\Models\Company;
use App\Models\Plan;
use App\Models\SaasCheckoutIntent;
use App\Services\AuditService;
use App\Services\CompanyService;
use App\Services\SaasAccessService;
use App\Services\WompiService;

class CompanyController extends Controller
{
    public function index(Request $request): void
    {
        $model = new Company();
        $companies = Auth::isSuperadmin()
            ? $model->all([], null, 'id DESC')
            : $model->all(['id' => (int) Tenant::companyId()], null);

        $this->render('empresas/index', [
            'title' => 'Empresas',
            'companies' => $companies,
        ]);
    }

    public function showRegister(Request $request): void
    {
        $plans = (new Plan())->all(['activo' => 1], null, 'precio_mensual ASC, id ASC');
        $wompiConfigured = (new WompiService())->isConfiguredForCheckout();

        $this->render('empresas/register', [
            'title' => 'Registrar empresa',
            'plans' => $plans,
            'wompi_configured' => $wompiConfigured,
            'guest_column_class' => 'col-12 col-lg-11 col-xl-10 col-xxl-9',
        ], 'layouts/guest');
    }

    public function register(Request $request): void
    {
        $companyName = trim((string) $request->input('nombre', ''));
        $companyEmail = trim((string) $request->input('email', ''));
        $adminName = trim((string) $request->input('admin_nombre', ''));
        $adminEmail = trim((string) $request->input('admin_email', ''));
        $adminPassword = (string) $request->input('admin_password', '');
        $adminPasswordConfirm = (string) $request->input('admin_password_confirm', '');
        $planId = (int) $request->input('plan_id', 0);

        Session::setOldInput($request->all());

        if ($companyName === '' || $adminName === '' || $adminEmail === '' || $adminPassword === '' || $planId <= 0) {
            flash('error', 'Completa los datos obligatorios para continuar con el pago.');
            redirect('registro-empresa');
        }

        if (!filter_var($adminEmail, FILTER_VALIDATE_EMAIL)) {
            flash('error', 'Correo de administrador inválido.');
            redirect('registro-empresa');
        }

        if (strlen($adminPassword) < 8) {
            flash('error', 'La contraseña debe tener mínimo 8 caracteres.');
            redirect('registro-empresa');
        }

        if ($adminPassword !== $adminPasswordConfirm) {
            flash('error', 'La confirmación de contraseña no coincide.');
            redirect('registro-empresa');
        }

        // Seguridad: el slug siempre se deriva del nombre de empresa
        // y no se acepta un valor manual enviado por el cliente.
        $slug = $this->sanitizeSlug($companyName);
        if ($slug === '') {
            flash('error', 'No se pudo generar un identificador de empresa válido.');
            redirect('registro-empresa');
        }

        $pdo = Database::connection();

        $planStmt = $pdo->prepare(
            'SELECT id, nombre, precio_mensual, activo
             FROM planes
             WHERE id = :id
             LIMIT 1'
        );
        $planStmt->execute([':id' => $planId]);
        $plan = $planStmt->fetch();

        if (!$plan || (int) ($plan['activo'] ?? 0) !== 1) {
            flash('error', 'El plan seleccionado no está disponible.');
            redirect('registro-empresa');
        }

        $userExistsStmt = $pdo->prepare('SELECT id FROM usuarios WHERE email = :email LIMIT 1');
        $userExistsStmt->execute([':email' => strtolower($adminEmail)]);
        if ((bool) $userExistsStmt->fetchColumn()) {
            flash('error', 'Ese correo ya existe en el sistema. Inicia sesión o usa otro correo.');
            redirect('registro-empresa');
        }

        $slugCompanyStmt = $pdo->prepare('SELECT id FROM empresas WHERE slug = :slug LIMIT 1');
        $slugCompanyStmt->execute([':slug' => $slug]);
        if ((bool) $slugCompanyStmt->fetchColumn()) {
            flash('error', 'Ese nombre de acceso ya existe. Usa otro nombre de empresa.');
            redirect('registro-empresa');
        }

        $slugIntentStmt = $pdo->prepare(
            'SELECT id
             FROM saas_checkout_intents
             WHERE empresa_slug = :slug
               AND estado IN ("pending", "approved", "provisioned")
             LIMIT 1'
        );
        $slugIntentStmt->execute([':slug' => $slug]);
        if ((bool) $slugIntentStmt->fetchColumn()) {
            flash('error', 'Ya existe un proceso de registro activo para ese nombre. Usa otro nombre.');
            redirect('registro-empresa');
        }

        $wompiService = new WompiService();
        $amountInCents = (int) round(((float) ($plan['precio_mensual'] ?? 0)) * 100);

        try {
            if ($amountInCents <= 0) {
                $today = date('Y-m-d');
                $endDate = date('Y-m-d', strtotime('+' . $wompiService->paidCycleDays() . ' days'));
                $created = (new CompanyService())->createCompanyWithAdmin([
                    'nombre' => $companyName,
                    'slug' => $slug,
                    'strict_slug' => true,
                    'email' => $companyEmail,
                    'nit' => $request->input('nit'),
                    'telefono' => $request->input('telefono'),
                    'direccion' => $request->input('direccion'),
                    'moneda' => $request->input('moneda', 'COP'),
                    'zona_horaria' => $request->input('zona_horaria', 'America/Bogota'),
                    'estado' => 'activa',
                ], [
                    'nombre' => $adminName,
                    'email' => $adminEmail,
                    'password' => $adminPassword,
                ], [
                    'plan_id' => (int) $plan['id'],
                    'fecha_inicio' => $today,
                    'fecha_vencimiento' => $endDate,
                    'estado' => 'activa',
                    'trial' => 0,
                    'auto_renovacion' => 1,
                ]);

                Session::clearOldInput();
                flash('success', 'Empresa registrada correctamente. Ya puedes iniciar sesión.');
                AuditService::track(
                    'empresa.registro.free',
                    'Empresa creada sin costo. ID: ' . (int) ($created['company_id'] ?? 0)
                );
                redirect('login');
            }

            if (!$wompiService->isConfiguredForCheckout()) {
                flash('error', 'El checkout de pagos no está configurado. Contacta al soporte.');
                redirect('registro-empresa');
            }

            $reference = $this->generateCheckoutReference();
            $redirectUrl = url('suscripcion/resultado?reference=' . rawurlencode($reference));

            $intentId = (new SaasCheckoutIntent())->create([
                'reference' => $reference,
                'plan_id' => (int) $plan['id'],
                'empresa_nombre' => $companyName,
                'empresa_slug' => $slug,
                'empresa_email' => strtolower($companyEmail),
                'admin_nombre' => $adminName,
                'admin_email' => strtolower($adminEmail),
                'admin_password_hash' => password_hash($adminPassword, PASSWORD_DEFAULT),
                'currency' => $wompiService->currency(),
                'amount_in_cents' => $amountInCents,
                'estado' => 'pending',
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ]);

            AuditService::track('saas.checkout.intent', 'Intento de checkout creado ID: ' . $intentId);
            Session::clearOldInput();

            $this->render('suscripciones/checkout', [
                'title' => 'Redirigiendo a Wompi',
                'checkout_url' => $wompiService->checkoutUrl(),
                'checkout_fields' => $wompiService->buildCheckoutFields(
                    $reference,
                    $amountInCents,
                    $redirectUrl,
                    $adminEmail
                ),
                'plan_name' => (string) ($plan['nombre'] ?? 'Plan'),
                'amount' => $amountInCents / 100,
                'reference' => $reference,
                'access_slug' => $slug,
            ], 'layouts/guest');
        } catch (\Throwable $e) {
            flash('error', 'No fue posible iniciar el checkout: ' . $e->getMessage());
            redirect('registro-empresa');
        }
    }

    public function select(Request $request): void
    {
        $userId = (int) Auth::id();

        $sql = 'SELECT e.id, e.nombre, e.estado
                FROM empresas e
                INNER JOIN usuario_empresa ue ON ue.empresa_id = e.id
                WHERE ue.usuario_id = :usuario_id
                ORDER BY e.nombre ASC';

        if (Auth::isSuperadmin()) {
            $sql = 'SELECT id, nombre, estado FROM empresas ORDER BY nombre ASC';
        }

        $stmt = Database::connection()->prepare($sql);

        if (Auth::isSuperadmin()) {
            $stmt->execute();
        } else {
            $stmt->execute([':usuario_id' => $userId]);
        }

        $companies = $stmt->fetchAll() ?: [];

        $this->render('empresas/select', [
            'title' => 'Seleccionar empresa',
            'companies' => $companies,
            'selected' => Tenant::companyId(),
        ]);
    }

    public function switch(Request $request): never
    {
        $companyId = (int) $request->input('empresa_id', 0);
        if ($companyId <= 0) {
            flash('error', 'Empresa inválida.');
            redirect('empresas/seleccionar');
        }

        if (!Auth::isSuperadmin()) {
            $stmt = Database::connection()->prepare(
                'SELECT 1 FROM usuario_empresa WHERE usuario_id = :usuario_id AND empresa_id = :empresa_id LIMIT 1'
            );
            $stmt->execute([
                ':usuario_id' => Auth::id(),
                ':empresa_id' => $companyId,
            ]);

            if (!(bool) $stmt->fetchColumn()) {
                flash('error', 'No tienes acceso a esta empresa.');
                redirect('empresas/seleccionar');
            }
        }

        if (!Auth::isSuperadmin()) {
            $access = (new SaasAccessService())->evaluateCompanyAccess($companyId, true);
            if (!(bool) ($access['allowed'] ?? false)) {
                flash('error', (string) ($access['message'] ?? 'La empresa seleccionada no está habilitada.'));
                redirect('empresas/seleccionar');
            }
        }

        Tenant::setCompanyId($companyId);
        AuditService::track('empresa.switch', 'Cambio de empresa activa a ID: ' . $companyId);
        flash('success', 'Empresa activa actualizada.');
        redirect('dashboard');
    }

    private function sanitizeSlug(string $value): string
    {
        $value = strtolower(trim($value));
        $value = preg_replace('/[^a-z0-9]+/i', '-', $value) ?: '';
        return trim($value, '-');
    }

    private function generateCheckoutReference(): string
    {
        return 'VX-' . date('YmdHis') . '-' . strtoupper(bin2hex(random_bytes(3)));
    }
}
