<?php
header("Content-Type: application/json");
date_default_timezone_set('America/Mexico_City');

require __DIR__ . "/vendor/autoload.php";

use PhpCfdi\CfdiSatScraper\SatScraper;
use PhpCfdi\CfdiSatScraper\Sessions\Fiel\FielSessionManager;
use PhpCfdi\Credentials\Credential;
use PhpCfdi\CfdiSatScraper\QueryByFilters;
use PhpCfdi\CfdiSatScraper\ResourceType;
use PhpCfdi\CfdiSatScraper\Filters\DownloadType;
use PhpCfdi\CfdiSatScraper\Filters\Options\StatesVoucherOption;
use PhpCfdi\CfdiSatScraper\Filters\Options\RfcOption;



// ==========================================================================
// 🔥 FUNCIÓN DE LOGS
// ==========================================================================
function workerLog($msg)
{
    $dir = __DIR__ . "/logs";
    if (!is_dir($dir)) mkdir($dir, 0777, true);

    $file = $dir . "/worker_" . date("Ymd") . ".log";
    $line = "[" . date('Y-m-d H:i:s') . "] $msg\n";

    file_put_contents($file, $line, FILE_APPEND);
}



workerLog("==============================================");
workerLog("🚀 Worker SAT iniciado.");
workerLog("==============================================");


// ==========================================================================
// 🟦 1. RECIBIR INPUT JSON
// ==========================================================================
$input = json_decode(file_get_contents('php://input'), true);

if (!$input) {
    workerLog("❌ ERROR: JSON no recibido.");
    echo json_encode(['status' => 'error', 'message' => 'Invalid JSON']);
    exit;
}

workerLog("📨 Parámetros recibidos: " . json_encode($input));


// ==========================================================================
// 🟥 2. VALIDAR PARÁMETROS
// ==========================================================================
$required = [
    'fechaInicio',
    'fechaFinal',
    'tipo',
    'estatusComprobante',
    'base64_cer',
    'base64_key',
    'password'
];

foreach ($required as $key) {
    if (empty($input[$key])) {
        workerLog("❌ Faltan parámetros. Clave faltante: $key");
        echo json_encode(['status' => 'error', 'message' => "Missing parameter: $key"]);
        exit;
    }
}


// ==========================================================================
// 🟧 3. CARGAR FIEL
// ==========================================================================
workerLog("🔐 Cargando certificado FIEL...");

try {
    $credential = Credential::create(
        base64_decode($input['base64_cer']),
        base64_decode($input['base64_key']),
        $input['password']
    );
} catch (Exception $e) {
    workerLog("❌ ERROR al cargar certificado: " . $e->getMessage());
    echo json_encode(['status' => 'error', 'message' => 'Error al cargar certificado FIEL']);
    exit;
}

if (!$credential->isFiel()) {
    workerLog("❌ Certificado NO es FIEL válido.");
    echo json_encode(['status' => 'error', 'message' => 'Certificado no es FIEL']);
    exit;
}

workerLog("✔ Certificado FIEL válido.");

$satScraper = new SatScraper(FielSessionManager::create($credential));


// ==========================================================================
// 🟩 4. CREAR CARPETAS DE TRABAJO
// ==========================================================================
$tmpFolder = __DIR__ . "/tmp/xml_" . time();
$zipFolder = __DIR__ . "/exports";

if (!is_dir($tmpFolder)) mkdir($tmpFolder, 0777, true);
if (!is_dir($zipFolder)) mkdir($zipFolder, 0777, true);

workerLog("📁 Carpeta temporal creada: $tmpFolder");


// ==========================================================================
// 🟦 5. PROCESAR RANGO DE FECHAS
// ==========================================================================
$fechaInicio = new DateTimeImmutable($input['fechaInicio']);
$fechaFinal  = new DateTimeImmutable($input['fechaFinal']);

$period = new DatePeriod($fechaInicio, new DateInterval('P1D'), $fechaFinal->modify('+1 day'));

$allUUIDs = [];

foreach ($period as $dia) {

    $fecha = $dia->format("Y-m-d");
    workerLog("📅 Procesando fecha: $fecha");

    try {
        $query = new QueryByFilters(
            new DateTimeImmutable($fecha),
            new DateTimeImmutable($fecha)
        );

        // Tipo de descarga
        $query->setDownloadType(
            ($input['tipo'] === 'recibidos')
                ? DownloadType::recibidos()
                : DownloadType::emitidos()
        );

        // Estatus comprobante
        if ($input['estatusComprobante'] == 'Vigentes')
            $query->setStateVoucher(StatesVoucherOption::vigentes());
        elseif ($input['estatusComprobante'] == 'Cancelados')
            $query->setStateVoucher(StatesVoucherOption::cancelados());
        else
            $query->setStateVoucher(StatesVoucherOption::todos());

        // RFC filtros
        if (!empty($input['rfcEmisor']))
            $query->setRfc(new RfcOption($input['rfcEmisor']));

        if (!empty($input['rfcReceptor']))
            $query->setRfc(new RfcOption($input['rfcReceptor']));

        // LISTAR
        $list = $satScraper->listByPeriod($query);

        // DESCARGAR
        $folderByDate = $tmpFolder . "/" . $fecha;
        mkdir($folderByDate, 0777, true);

        $downloaded = $satScraper
            ->resourceDownloader(ResourceType::xml(), $list, 50)
            ->saveTo($folderByDate, true, 0777);

        $count = count($downloaded);

        workerLog("📥 Descargados $count XML para fecha $fecha");

        $allUUIDs = array_merge($allUUIDs, $downloaded);
    } catch (Exception $e) {
        workerLog("❌ Error en fecha $fecha: " . $e->getMessage());
    }

    // Pausa para evitar bloqueo del SAT
    usleep(800000);
}


// ==========================================================================
// 🟪 6. GENERAR ZIP
// ==========================================================================
$zipPath = $zipFolder . "/proc_" . time() . ".zip";

$zip = new ZipArchive();
if ($zip->open($zipPath, ZipArchive::CREATE)) {

    $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tmpFolder));

    foreach ($rii as $file) {
        if ($file->isDir()) continue;

        $relative = substr($file->getPathname(), strlen($tmpFolder) + 1);
        $zip->addFile($file->getPathname(), $relative);
    }

    $zip->close();
    workerLog("📦 ZIP generado: $zipPath");
} else {
    workerLog("❌ No se pudo crear ZIP.");
}


// ==========================================================================
// 🟦 7. RESPUESTA AL SERVIDOR PRINCIPAL
// ==========================================================================
$response = [
    'status' => 'ok',
    'total' => count($allUUIDs),
    'uuids' => $allUUIDs,
    'zip_url' => "http://localhost/api_kpl/exports/" . basename($zipPath)
];

workerLog("📤 Respuesta enviada: " . json_encode($response));

echo json_encode($response, JSON_UNESCAPED_UNICODE);
