<?php

namespace App\Http\Controllers\Master;

use App\Http\Controllers\Auth\RegisterController;
use App\Http\Controllers\Controller;
use App\Jobs\SincronizarEmpresaJob;
use App\Models\Company;
use App\Models\NotaFiscal;
use App\Models\SyncLog;
use App\Models\User;
use App\Rules\Cnpj;
use App\Services\Sefaz\CertificateService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;
use Illuminate\View\View;

class CompanyController extends Controller
{
    public function index(): View
    {
        return view('master.empresas.index');
    }

    public function create(): View
    {
        return view('master.empresas.create', ['ufs' => RegisterController::UFS]);
    }

    public function store(Request $request): RedirectResponse
    {
        $dados = $request->validate([
            'razao_social' => ['required', 'string', 'max:180'],
            'nome_fantasia' => ['nullable', 'string', 'max:180'],
            'cnpj' => ['required', 'string', new Cnpj],
            'ie' => ['nullable', 'string', 'max:20'],
            'uf' => ['required', Rule::in(RegisterController::UFS)],
            'email' => ['required', 'email', 'max:180'],
            'telefone' => ['nullable', 'string', 'max:20'],
            'plano' => ['required', 'string', 'max:30'],
            'assinatura_expira_em' => ['nullable', 'date'],
            'admin_name' => ['required', 'string', 'max:120'],
            'admin_email' => ['required', 'email', 'max:180', Rule::unique('users', 'email')],
            'admin_password' => ['required', Password::min(8)->letters()->numbers()],
        ], [], ['razao_social' => 'razão social']);

        $cnpj = preg_replace('/\D/', '', $dados['cnpj']);

        if (Company::withTrashed()->where('cnpj', $cnpj)->exists()) {
            return back()->withInput()->withErrors(['cnpj' => 'Já existe empresa com este CNPJ.']);
        }

        DB::transaction(function () use ($dados, $cnpj) {
            $company = Company::create([
                'cnpj' => $cnpj,
                'razao_social' => $dados['razao_social'],
                'nome_fantasia' => $dados['nome_fantasia'] ?? null,
                'ie' => $dados['ie'] ?? null,
                'uf' => $dados['uf'],
                'email' => $dados['email'],
                'telefone' => $dados['telefone'] ?? null,
                'plano' => $dados['plano'],
                'assinatura_expira_em' => $dados['assinatura_expira_em'] ?? null,
            ]);

            User::create([
                'company_id' => $company->id,
                'name' => $dados['admin_name'],
                'email' => $dados['admin_email'],
                'password' => $dados['admin_password'],
                'role' => User::ROLE_ADMIN,
            ]);
        });

        return redirect()->route('master.empresas.index')->with('status', 'Empresa cadastrada.');
    }

    public function show(Company $empresa): View
    {
        return view('master.empresas.show', [
            'empresa' => $empresa->loadCount('notasFiscais', 'users'),
            'ufs' => RegisterController::UFS,
            'notas' => NotaFiscal::withoutGlobalScopes()
                ->where('company_id', $empresa->id)
                ->latest('data_emissao')
                ->limit(10)
                ->get(),
            'logs' => SyncLog::withoutGlobalScopes()
                ->where('company_id', $empresa->id)
                ->latest()
                ->limit(10)
                ->get(),
            'valorTotal' => NotaFiscal::withoutGlobalScopes()
                ->where('company_id', $empresa->id)
                ->sum('valor_total'),
        ]);
    }

    public function update(Request $request, Company $empresa): RedirectResponse
    {
        $dados = $request->validate([
            'razao_social' => ['required', 'string', 'max:180'],
            'nome_fantasia' => ['nullable', 'string', 'max:180'],
            'ie' => ['nullable', 'string', 'max:20'],
            'uf' => ['required', Rule::in(RegisterController::UFS)],
            'email' => ['required', 'email', 'max:180'],
            'telefone' => ['nullable', 'string', 'max:20'],
            'plano' => ['required', 'string', 'max:30'],
            'limite_notas_mes' => ['required', 'integer', 'min:0'],
            'assinatura_expira_em' => ['nullable', 'date'],
            'is_active' => ['boolean'],
            'monitor_enabled' => ['boolean'],
            'manifestacao_automatica' => ['boolean'],
            'monitor_intervalo_min' => ['required', 'integer', 'min:60', 'max:1440'],
            'ambiente' => ['required', 'in:1,2'],
        ], [], ['razao_social' => 'razão social']);

        $empresa->forceFill([
            ...$dados,
            'is_active' => $request->boolean('is_active'),
            'monitor_enabled' => $request->boolean('monitor_enabled'),
            'manifestacao_automatica' => $request->boolean('manifestacao_automatica'),
        ])->save();

        return back()->with('status', 'Empresa atualizada.');
    }

    public function destroy(Company $empresa, CertificateService $certificados): RedirectResponse
    {
        $certificados->forget($empresa, persist: true);
        $empresa->users()->update(['is_active' => false]);
        $empresa->delete();

        return redirect()->route('master.empresas.index')
            ->with('status', 'Empresa desativada. Os XMLs continuam arquivados para fins fiscais.');
    }

    /** Reenfileira a sincronização, ignorando o intervalo mínimo local. */
    public function sincronizar(Company $empresa): RedirectResponse
    {
        if (! $empresa->hasCertificate()) {
            return back()->withErrors(['monitor' => 'Empresa sem certificado digital instalado.']);
        }

        SincronizarEmpresaJob::dispatch($empresa->id, 'manual');

        return back()->with('status', 'Sincronização enfileirada para '.$empresa->razao_social.'.');
    }

    /**
     * Reinicia o cursor NSU. Faz a próxima sincronização varrer a fila da
     * SEFAZ desde o começo — usar só quando faltarem documentos antigos,
     * porque consome várias requisições.
     */
    public function reiniciarNsu(Company $empresa): RedirectResponse
    {
        $empresa->forceFill(['ult_nsu' => 0, 'max_nsu' => 0])->save();

        return back()->with('status', 'Cursor NSU reiniciado. A próxima sincronização varre a fila desde o início.');
    }
}
