<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreDebitNoteRequest;
use App\Models\AuditLog;
use App\Models\DebitNote;
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 DebitNoteController extends Controller
{
    public function __construct(
        private CreditService $creditService,
    ) {}

    public function index(Request $request): Response
    {
        $query = DebitNote::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);
        }

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

        return Inertia::render('Admin/DebitNotes/Index', [
            'debitNotes' => $debitNotes,
            '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')
            ->latest()
            ->limit(200)
            ->get();

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

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

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

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

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

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

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

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

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

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

        return $pdf->download("debit-note-{$debitNote->number}.pdf");
    }

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

        $this->creditService->voidDebitNote($debitNote);

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

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