<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Client;
use App\Models\Contract;
use App\Models\Invoice;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class InvoiceController extends Controller
{
    private array $statuses = [
        'paid' => 'Paga',
        'pending' => 'Pendente',
        'overdue' => 'Vencida',
        'cancelled' => 'Cancelada',
    ];

    public function index()
    {
        $invoices = Invoice::with(['client', 'contract'])->latest()->paginate(10);

        return view('admin.shared.index', [
            'title' => 'Faturação',
            'subtitle' => 'Faturas emitidas, vencimentos e estado de pagamento.',
            'createRoute' => route('admin.invoices.create'),
            'createLabel' => 'Nova Fatura',
            'columns' => ['Cliente', 'Contrato', 'Valor', 'Emissão', 'Vencimento', 'Estado'],
            'rows' => $invoices->map(fn (Invoice $invoice) => [
                'values' => [
                    $invoice->client->name ?? 'Sem cliente',
                    $invoice->contract ? ('Contrato #' . $invoice->contract->id) : 'Sem contrato',
                    number_format((float) $invoice->amount, 2, ',', '.') . ' Kz',
                    $invoice->issue_date->format('d/m/Y'),
                    $invoice->due_date?->format('d/m/Y') ?? 'Sem vencimento',
                    $this->statuses[$invoice->status] ?? $invoice->status,
                ],
                'editRoute' => route('admin.invoices.edit', $invoice),
                'deleteRoute' => route('admin.invoices.destroy', $invoice),
            ]),
            'paginator' => $invoices,
            'emptyLabel' => 'Nenhuma fatura registada.',
        ]);
    }

    public function create()
    {
        return $this->form(new Invoice(), route('admin.invoices.store'), 'Nova Fatura');
    }

    public function store(Request $request)
    {
        Invoice::create($this->validated($request));

        return redirect()->route('admin.invoices.index')->with('success', 'Fatura cadastrada com sucesso.');
    }

    public function show(Invoice $invoice)
    {
        return redirect()->route('admin.invoices.edit', $invoice);
    }

    public function edit(Invoice $invoice)
    {
        return $this->form($invoice, route('admin.invoices.update', $invoice), 'Editar Fatura', 'PUT');
    }

    public function update(Request $request, Invoice $invoice)
    {
        $invoice->update($this->validated($request));

        return redirect()->route('admin.invoices.index')->with('success', 'Fatura atualizada com sucesso.');
    }

    public function destroy(Invoice $invoice)
    {
        $invoice->delete();

        return redirect()->route('admin.invoices.index')->with('success', 'Fatura removida com sucesso.');
    }

    private function form(Invoice $invoice, string $action, string $title, string $method = 'POST')
    {
        return view('admin.shared.form', [
            'title' => $title,
            'subtitle' => 'Registe o valor, datas e estado financeiro.',
            'backRoute' => route('admin.invoices.index'),
            'action' => $action,
            'method' => $method,
            'submitLabel' => $method === 'POST' ? 'Cadastrar Fatura' : 'Guardar Alterações',
            'fields' => [
                ['name' => 'client_id', 'label' => 'Cliente *', 'type' => 'select', 'value' => $invoice->client_id, 'options' => Client::orderBy('name')->pluck('name', 'id')],
                ['name' => 'contract_id', 'label' => 'Contrato', 'type' => 'select', 'value' => $invoice->contract_id, 'options' => Contract::with('client')->get()->mapWithKeys(fn ($contract) => [$contract->id => 'Contrato #' . $contract->id . ' - ' . ($contract->client->name ?? 'Cliente')]), 'empty' => 'Sem contrato'],
                ['name' => 'amount', 'label' => 'Valor *', 'type' => 'number', 'step' => '0.01', 'value' => $invoice->amount],
                ['name' => 'issue_date', 'label' => 'Data de Emissão *', 'type' => 'date', 'value' => optional($invoice->issue_date)->format('Y-m-d')],
                ['name' => 'due_date', 'label' => 'Data de Vencimento', 'type' => 'date', 'value' => optional($invoice->due_date)->format('Y-m-d')],
                ['name' => 'path_to_pdf', 'label' => 'Caminho do PDF', 'type' => 'text', 'value' => $invoice->path_to_pdf],
                ['name' => 'status', 'label' => 'Estado *', 'type' => 'select', 'value' => $invoice->status ?: 'pending', 'options' => $this->statuses],
            ],
        ]);
    }

    private function validated(Request $request): array
    {
        return $request->validate([
            'client_id' => ['required', 'exists:clients,id'],
            'contract_id' => ['nullable', 'exists:contracts,id'],
            'amount' => ['required', 'numeric', 'min:0'],
            'issue_date' => ['required', 'date'],
            'due_date' => ['nullable', 'date', 'after_or_equal:issue_date'],
            'path_to_pdf' => ['nullable', 'string', 'max:255'],
            'status' => ['required', Rule::in(array_keys($this->statuses))],
        ]);
    }
}
