<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreCreditNoteRequest;
use App\Models\AuditLog;
use App\Models\CreditNote;
use App\Models\Invoice;
use App\Models\User;
use App\Services\Billing\CreditService;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class CreditNoteController extends Controller
{
    public function __construct(
        private CreditService $creditService,
    ) {}

    public function index(Request $request): Response
    {
        $query = CreditNote::query()
            ->with('user:id,name,email');

        if ($search = $request->input('search')) {
            $query->where(function ($q) use ($search): void {
                $q->where('number', 'like', "%{$search}%")
                    ->orWhereHas('user', function ($uq) use ($search): void {
                        $uq->where('name', 'like', "%{$search}%")
                            ->orWhere('email', 'like', "%{$search}%");
                    });
            });
        }

        if ($status = $request->input('status')) {
            $query->where('status', $status);
        }

        $creditNotes = $query->latest()->paginate(15)->withQueryString();

        return Inertia::render('Admin/CreditNotes/Index', [
            'creditNotes' => $creditNotes,
            'filters' => [
                'search' => $request->input('search', ''),
                'status' => $request->input('status', ''),
            ],
        ]);
    }

    public function create(): Response
    {
        $customers = User::query()
            ->select('id', 'name', 'email', 'credit_balance')
            ->orderBy('name')
            ->get();

        $invoices = Invoice::query()
            ->select('id', 'number', 'user_id', 'total', 'status')
            ->whereIn('status', ['paid', 'pending', 'overdue'])
            ->latest()
            ->limit(200)
            ->get();

        return Inertia::render('Admin/CreditNotes/Create', [
            'customers' => $customers,
            'invoices' => $invoices,
        ]);
    }

    public function store(StoreCreditNoteRequest $request): RedirectResponse
    {
        $validated = $request->validated();

        $user = User::findOrFail($validated['user_id']);
        $invoice = isset($validated['invoice_id']) ? Invoice::find($validated['invoice_id']) : null;

        $creditNote = $this->creditService->issueCreditNote(
            user: $user,
            amount: (float) $validated['amount'],
            reason: $validated['reason'] ?? null,
            invoice: $invoice,
            creator: $request->user(),
        );

        AuditLog::create([
            'user_id' => $user->id,
            'admin_id' => $request->user()?->id,
            'action' => 'issue_credit_note',
            'resource_type' => 'credit_note',
            'resource_id' => $creditNote->id,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'changes' => [
                'amount' => $validated['amount'],
                'reason' => $validated['reason'] ?? null,
            ],
        ]);

        return redirect()->route('credit-notes.show', $creditNote)
            ->with('success', "Credit note {$creditNote->number} has been issued.");
    }

    public function show(CreditNote $creditNote): Response
    {
        $creditNote->load([
            'user:id,name,email,credit_balance',
            'invoice:id,number,total,status',
            'creator:id,name,email',
            'accountCredits',
        ]);

        return Inertia::render('Admin/CreditNotes/Show', [
            'creditNote' => $creditNote,
        ]);
    }

    public function download(CreditNote $creditNote): \Symfony\Component\HttpFoundation\Response
    {
        $creditNote->load(['user', 'invoice']);

        $pdf = Pdf::loadView('pdf.credit-note', ['creditNote' => $creditNote]);

        return $pdf->download("credit-note-{$creditNote->number}.pdf");
    }

    public function void(Request $request, CreditNote $creditNote): RedirectResponse
    {
        if ($creditNote->status === 'voided') {
            return redirect()->back()->with('error', 'This credit note is already voided.');
        }

        $this->creditService->voidCreditNote($creditNote);

        AuditLog::create([
            'user_id' => $creditNote->user_id,
            'admin_id' => $request->user()?->id,
            'action' => 'void_credit_note',
            'resource_type' => 'credit_note',
            'resource_id' => $creditNote->id,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
        ]);

        return redirect()->back()->with('success', "Credit note {$creditNote->number} has been voided.");
    }
}
