<?php

namespace App\Http\Controllers\Painel;

use App\Http\Controllers\Controller;
use App\Models\NotaFiscal;
use App\Services\PacoteXmlService;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * Exporta vários XMLs num único .zip, organizado por competência.
 *
 * O pacote é montado em arquivo temporário e removido após o envio —
 * hospedagem compartilhada não tem folga de memória para montá-lo em RAM.
 */
class DownloadLoteController extends Controller
{
    public function __invoke(Request $request, PacoteXmlService $pacotes): BinaryFileResponse
    {
        $filtros = $request->validate([
            'ids' => ['nullable', 'array'],
            'ids.*' => ['integer'],
            'de' => ['nullable', 'date'],
            'ate' => ['nullable', 'date', 'after_or_equal:de'],
            'emit_cnpj' => ['nullable', 'string', 'max:18'],
            'situacao' => ['nullable', 'in:autorizada,cancelada,denegada'],
            'agrupar' => ['nullable', 'in:emissao,recebimento'],
            'eventos' => ['nullable', 'boolean'],
        ]);

        $agrupar = $filtros['agrupar'] ?? 'emissao';
        $porRecebimento = $agrupar === 'recebimento';

        $notas = NotaFiscal::query()
            ->completas()
            ->whereNotNull('xml_path')
            ->when($filtros['ids'] ?? null, fn ($q, $ids) => $q->whereIn('id', $ids))
            ->when($filtros['situacao'] ?? null, fn ($q, $s) => $q->where('situacao', $s))
            ->when(
                $filtros['emit_cnpj'] ?? null,
                fn ($q, $cnpj) => $q->where('emit_cnpj', preg_replace('/\D/', '', $cnpj))
            )
            // O período segue o mesmo critério do agrupamento: filtrar por
            // emissão e agrupar por recebimento produziria pastas fora do
            // intervalo pedido.
            ->when($filtros['de'] ?? null, fn ($q, $de) => $porRecebimento
                ? $q->whereDate('created_at', '>=', $de)
                : $q->whereDate('data_emissao', '>=', $de))
            ->when($filtros['ate'] ?? null, fn ($q, $ate) => $porRecebimento
                ? $q->whereDate('created_at', '<=', $ate)
                : $q->whereDate('data_emissao', '<=', $ate))
            ->orderBy($porRecebimento ? 'created_at' : 'data_emissao')
            ->limit(PacoteXmlService::MAX_NOTAS)
            ->get();

        abort_if($notas->isEmpty(), 404, 'Nenhum XML disponível para os filtros selecionados.');

        $pacote = $pacotes->montar(
            $notas,
            $request->user()->company,
            $agrupar,
            $request->boolean('eventos', true),
        );

        return response()
            ->download($pacote['caminho'], $pacote['nome'], ['Content-Type' => 'application/zip'])
            ->deleteFileAfterSend();
    }
}
