<?php

namespace App\Http\Controllers\Master;

use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Services\Sefaz\CertificateService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

/**
 * Certificados digitais de todas as empresas.
 *
 * O master não tem certificado próprio — o que ele precisa é enxergar o
 * parque inteiro: quem está sem, quem já venceu e quem vence em breve,
 * já que certificado vencido para o monitor da empresa.
 */
class CertificadoGlobalController extends Controller
{
    public function index(Request $request): View
    {
        $filtro = $request->query('status', '');

        $todas = Company::query()
            ->orderByRaw('cert_valid_to is null')   // sem certificado por último
            ->orderBy('cert_valid_to')
            ->get();

        // Grupos mutuamente exclusivos: uma empresa cai em exatamente um.
        // Sem isso os totais se sobrepõem — empresa sem o arquivo no disco
        // aparecia ao mesmo tempo como "sem certificado" e como "vencida".
        $situacoes = $todas->mapWithKeys(fn (Company $e) => [$e->id => $this->situacao($e)]);

        return view('master.certificados', [
            'empresas' => $filtro
                ? $todas->filter(fn (Company $e) => $situacoes[$e->id] === $filtro)
                : $todas,
            'situacoes' => $situacoes,
            'filtro' => $filtro,
            'resumo' => [
                'total' => $todas->count(),
                'ok' => $situacoes->filter(fn ($s) => $s === 'ok')->count(),
                'vencendo' => $situacoes->filter(fn ($s) => $s === 'vencendo')->count(),
                'vencido' => $situacoes->filter(fn ($s) => $s === 'vencido')->count(),
                'sem' => $situacoes->filter(fn ($s) => $s === 'sem')->count(),
            ],
        ]);
    }

    /**
     * "Sem certificado" cobre tanto o campo vazio quanto o arquivo ausente do
     * disco — nos dois casos o monitor não roda, e a distinção não ajuda quem
     * está olhando a tela.
     */
    private function situacao(Company $empresa): string
    {
        return match (true) {
            ! $empresa->hasCertificate() => 'sem',
            $empresa->certificateExpired() => 'vencido',
            $empresa->certificateExpiringSoon() => 'vencendo',
            default => 'ok',
        };
    }

    /**
     * Instala o certificado em nome da empresa. Existe para o suporte: é
     * comum o cliente enviar o .pfx por outro canal em vez de subir sozinho.
     */
    public function store(Request $request, Company $empresa, CertificateService $certificados): RedirectResponse
    {
        $request->validate([
            'certificado' => ['required', 'file', 'max:512'],
            'senha' => ['required', 'string', 'max:120'],
        ], [
            'certificado.max' => 'O arquivo do certificado deve ter no máximo 512 KB.',
        ], ['senha' => 'senha do certificado']);

        $extensao = strtolower($request->file('certificado')->getClientOriginalExtension());

        if (! in_array($extensao, ['pfx', 'p12'], true)) {
            return back()->withErrors(['certificado' => 'O certificado precisa ser um arquivo .pfx ou .p12.']);
        }

        try {
            $info = $certificados->store($empresa, $request->file('certificado'), $request->input('senha'));
        } catch (\Throwable $e) {
            return back()->withErrors(['certificado' => $e->getMessage()]);
        }

        return back()->with('status', sprintf(
            'Certificado de %s instalado. Válido até %s.',
            $empresa->razao_social,
            $info['valid_to']->format('d/m/Y'),
        ));
    }

    public function destroy(Company $empresa, CertificateService $certificados): RedirectResponse
    {
        $certificados->forget($empresa, persist: true);
        $empresa->forceFill(['monitor_enabled' => false])->save();

        return back()->with('status', 'Certificado removido e monitor desativado para '.$empresa->razao_social.'.');
    }
}
