<?php

require_once '../../core/config.php';
require_once '../../core/session.php';
require_once '../../core/database.php';
require_once '../../core/auth.php';
require_once '../../core/permissions.php';
require_once '../../services/billing/BillingRuntimeGate.php';
require_once '../../services/billing/BillingIssueValidationService.php';

require_login();
csrf_require_valid_request();
header('Content-Type: application/json; charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(array('success' => false, 'message' => 'Método no permitido.'));
    exit;
}

if (!user_can('module.billing') && !user_can('billing.prepare') && !user_can('billing.admin') && current_user_role() !== 'admin') {
    http_response_code(403);
    echo json_encode(array('success' => false, 'message' => 'No tienes permisos para preparar facturación.'));
    exit;
}

$quoteId = (int)($_POST['quote_id'] ?? 0);
$documentKey = trim((string)($_POST['document_key'] ?? 'invoice_electronic'));
$allowedDocumentKeys = array('invoice_electronic', 'invoice_exempt_electronic', 'invoice_export_electronic');
if ($quoteId <= 0 || !in_array($documentKey, $allowedDocumentKeys, true)) {
    http_response_code(400);
    echo json_encode(array('success' => false, 'message' => 'Cotización o tipo documental no válido.'));
    exit;
}

try {
    $pdo = db();
    $stmt = $pdo->prepare('SELECT id, quote_number, customer_id, status, total, facto_document_id, invoice_number FROM crm_quotes WHERE id=? LIMIT 1');
    $stmt->execute(array($quoteId));
    $quote = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$quote) {
        throw new RuntimeException('Cotización no encontrada.');
    }

    $environment = billing_runtime_environment(null);
    $userId = function_exists('current_user_id') ? (int)current_user_id() : 0;
    $customerId = (int)$quote['customer_id'];
    $totalAmount = (float)$quote['total'];
    $isAdmin = user_can('billing.admin') || current_user_role() === 'admin';
    $hasIssuePermission = $isAdmin || ($environment === 'production'
        ? user_can('billing.issue.production')
        : user_can('billing.issue.sandbox'));

    $checks = array();
    $addCheck = static function ($key, $label, $ok, $detail, $required = true) use (&$checks) {
        $checks[] = array(
            'key' => (string)$key,
            'label' => (string)$label,
            'ok' => (bool)$ok,
            'detail' => (string)$detail,
            'required' => (bool)$required,
        );
    };

    $validation = null;
    $validationErrors = array();
    $validationWarnings = array();
    try {
        $validator = new BillingIssueValidationService($pdo);
        $validation = $validator->validateQuoteForIssue($quoteId, $documentKey, array(
            'environment' => $environment,
            'issue_date' => $_POST['issue_date'] ?? date('Y-m-d'),
            'payment_terms' => $_POST['payment_terms'] ?? 'contado',
            'currency_code' => $_POST['currency_code'] ?? 'CLP',
            'exchange_rate_value' => $_POST['exchange_rate_value'] ?? null,
            'receiver_country_id' => $_POST['receiver_country_id'] ?? null,
            'receiver_tax_id_code' => $_POST['receiver_tax_id_code'] ?? null,
            'receiver_tax_id_type' => $_POST['receiver_tax_id_type'] ?? null,
            'receiver_legal_name' => $_POST['receiver_legal_name'] ?? null,
            'receiver_address' => $_POST['receiver_address'] ?? null,
            'receiver_district' => $_POST['receiver_district'] ?? null,
            'receiver_city' => $_POST['receiver_city'] ?? null,
            'receiver_phone' => $_POST['receiver_phone'] ?? null,
            'receiver_activity' => $_POST['receiver_activity'] ?? null,
            'receiver_email' => $_POST['receiver_email'] ?? null,
            'export_pricing_mode' => $_POST['export_pricing_mode'] ?? 'convert_from_clp',
            'sale_modality' => $_POST['sale_modality'] ?? null,
            'sale_clause' => $_POST['sale_clause'] ?? null,
        ));
        $validationErrors = isset($validation['errors']) && is_array($validation['errors']) ? $validation['errors'] : array();
        $validationWarnings = isset($validation['warnings']) && is_array($validation['warnings']) ? $validation['warnings'] : array();
    } catch (Throwable $validationError) {
        $validationErrors[] = $validationError->getMessage();
    }

    if ($environment === 'production') {
        $gateState = billing_runtime_gate_state('production');
        $factoState = billing_production_facto_config_state();
        $appEnvOk = defined('APP_ENV') && APP_ENV === 'production';
        $addCheck('environment', 'Ambiente fijado por el servidor', true, 'Producción · documento tributario real');
        $addCheck('app_env', 'Aplicación habilitada', $appEnvOk, $appEnvOk ? 'Configuración correcta' : 'La aplicación no está habilitada para emisión real');
        $addCheck('facto_config', 'Credenciales FACTO producción', !empty($factoState['complete']), !empty($factoState['complete'])
            ? 'Conexión tributaria disponible'
            : 'La conexión tributaria productiva no está completa');
        $addCheck('read_gate', 'Consulta tributaria', !empty($gateState['read_enabled']), !empty($gateState['read_enabled']) ? 'Habilitada' : 'Deshabilitada por administración');
        $addCheck('finance_gate', 'Integración financiera', !empty($gateState['finance_enabled']), !empty($gateState['finance_enabled']) ? 'Habilitada' : 'Deshabilitada por administración');
        $addCheck('issue_gate', 'Emisión de facturas', !empty($gateState['issue_enabled']), !empty($gateState['issue_enabled']) ? 'Habilitada' : 'Deshabilitada por administración');
        $addCheck('permission', 'Permiso del usuario', $hasIssuePermission, $hasIssuePermission ? 'Usuario autorizado' : 'Solicita el permiso Emitir facturas reales');

        $policy = billing_runtime_issue_policy_state('production', array(), array(
            'document_key' => $documentKey,
            'user_id' => $userId,
            'customer_id' => $customerId,
            'total_amount' => $totalAmount,
        ));
        $addCheck('policy_mode', 'Acceso productivo', true, !empty($policy['canary_mode'])
            ? 'Piloto restringido'
            : 'Usuarios habilitados y todos los clientes');
        $addCheck('document_allowlist', 'Tipo documental autorizado', !empty($policy['document_allowed']), !empty($policy['document_allowed'])
            ? $documentKey
            : 'Tipo de factura no habilitado por la configuración del servidor');
        $addCheck('user_allowlist', 'Usuario habilitado', !empty($policy['user_allowed']), !empty($policy['user_allowed'])
            ? (!empty($policy['user_allowlist_configured']) ? 'Incluido en la restricción adicional' : 'Habilitado desde Administración de usuarios')
            : 'El usuario no está autorizado para emitir facturas reales');
        $addCheck('customer_allowlist', 'Cliente habilitado', !empty($policy['customer_allowed']), !empty($policy['customer_allowed'])
            ? (!empty($policy['customer_allowlist_configured']) ? 'Incluido en la restricción adicional' : 'Sin restricción por cliente')
            : 'El cliente no está autorizado para este período de emisión');
        $addCheck('pilot_window', 'Vigencia productiva', !empty($policy['pilot_window_ok']), !empty($policy['pilot_window_ok'])
            ? (!empty($policy['pilot_ends_at']) ? 'Vigente hasta ' . $policy['pilot_ends_at'] : 'Sin ventana piloto')
            : 'La ventana productiva no está vigente');

        $maxTotal = (float)$policy['max_total_amount'];
        $amountOk = !empty($policy['amount_allowed']);
        $addCheck('amount_limit', 'Monto autorizado', $amountOk, $amountOk
            ? '$' . number_format($totalAmount, 0, ',', '.') . ($maxTotal > 0 ? ' de $' . number_format($maxTotal, 0, ',', '.') : '')
            : 'El total supera el monto máximo autorizado para una factura');
    } else {
        $addCheck('environment', 'Ambiente fijado por el servidor', true, 'Sandbox · documento de prueba');
        $addCheck('permission', 'Permiso del usuario', $hasIssuePermission, $hasIssuePermission ? 'Usuario autorizado' : 'Asigna billing.issue.sandbox');
    }

    $validationOk = is_array($validation) && !empty($validation['ok']);
    $addCheck('tax_validation', 'Datos tributarios de la cotización', $validationOk, $validationOk ? 'Validación local aprobada' : (isset($validationErrors[0]) ? $validationErrors[0] : 'Validación pendiente'));

    $ready = true;
    foreach ($checks as $check) {
        if (!empty($check['required']) && empty($check['ok'])) {
            $ready = false;
            break;
        }
    }

    echo json_encode(array(
        'success' => true,
        'result' => array(
            'ready' => $ready,
            'environment' => $environment,
            'environment_label' => $environment === 'production' ? 'Producción · documento real' : 'Sandbox · prueba',
            'preview_mode' => $environment === 'production' ? 'local_validation' : 'facto_remote',
            'confirmation_text' => billing_issue_confirmation_text($environment),
            'checks' => $checks,
            'validation_errors' => array_values($validationErrors),
            'validation_warnings' => array_values($validationWarnings),
            'context' => array(
                'quote_id' => (int)$quote['id'],
                'quote_number' => (string)$quote['quote_number'],
                'user_id' => $userId,
                'customer_id' => $customerId,
                'total_amount' => $totalAmount,
            ),
        ),
    ), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
} catch (Throwable $e) {
    http_response_code(400);
    echo json_encode(array('success' => false, 'message' => $e->getMessage()), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
