<?php

namespace App\Http\Controllers;

use App\Models\MexcoInvoice;
use App\Services\AuditService;
use App\Services\BillingService;
use App\Services\NotificationService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class MexcoSuperAdminInvoiceController extends Controller
{
    public function __construct(
        private BillingService $billing,
        private AuditService $audit,
        private NotificationService $notifications,
    ) {}

    public function index(Request $request): View
    {
        $status = $request->input('status', '');
        $q = strtolower(trim($request->input('q', '')));

        $invoices = MexcoInvoice::query()
            ->with(['organisation', 'event', 'license.plan'])
            ->when($status, fn ($query) => $query->where('status', $status))
            ->when($q, fn ($query) => $query->where(function ($sub) use ($q) {
                $sub->where('invoice_number', 'like', "%{$q}%")
                    ->orWhereHas('organisation', fn ($org) => $org->where('name', 'like', "%{$q}%"))
                    ->orWhereHas('event', fn ($evt) => $evt->where('name', 'like', "%{$q}%")->orWhere('id', 'like', "%{$q}%"));
            }))
            ->orderByDesc('created_at')
            ->get();

        return view('super-admin.invoices.index', compact('invoices', 'status', 'q'));
    }

    public function show(MexcoInvoice $invoice): View
    {
        $invoice->load(['organisation', 'event', 'license.plan', 'items', 'payments', 'promoCode']);
        $availableCredit = $this->billing->availableCreditCents($invoice->organisation_id);

        return view('super-admin.invoices.show', compact('invoice', 'availableCredit'));
    }

    public function issue(MexcoInvoice $invoice): RedirectResponse
    {
        $invoice = $this->billing->issueInvoice($invoice);

        $this->audit->log('invoice.issued', MexcoInvoice::class, (string) $invoice->id, null, [
            'invoice_number' => $invoice->invoice_number,
            'total_cents' => $invoice->total_cents,
        ]);

        $recipient = $invoice->organisation?->email ?? $invoice->event?->organiser_username;
        if ($recipient) {
            $this->notifications->send('invoice_issued', $recipient, [
                'invoice_number' => $invoice->invoice_number,
                'event_name' => $invoice->event?->name ?? $invoice->event_id,
                'amount' => $invoice->formattedTotal(),
                'due_date' => $invoice->due_at?->format('d M Y') ?? '',
            ], MexcoInvoice::class, (string) $invoice->id);
        }

        return back()->with('success', 'Invoice issued to '.$invoice->organisation->name.'.');
    }

    public function cancel(MexcoInvoice $invoice): RedirectResponse
    {
        $this->billing->cancelInvoice($invoice);

        return back()->with('success', 'Invoice cancelled.');
    }

    public function applyPromo(Request $request, MexcoInvoice $invoice): RedirectResponse
    {
        $data = $request->validate(['promo_code' => 'required|string|max:32']);

        $this->billing->applyPromoCode($invoice, $data['promo_code']);

        return back()->with('success', 'Promo code applied.');
    }

    public function applyCredit(Request $request, MexcoInvoice $invoice): RedirectResponse
    {
        $data = $request->validate(['amount_cents' => 'nullable|integer|min:1']);

        $this->billing->applyOrganisationCredit($invoice, $data['amount_cents'] ?? null);

        return back()->with('success', 'Organisation credit applied to invoice.');
    }

    public function recordPayment(Request $request, MexcoInvoice $invoice): RedirectResponse
    {
        $data = $request->validate([
            'amount_cents' => 'required|integer|min:1',
            'reference' => 'nullable|string|max:255',
            'notes' => 'nullable|string|max:1000',
        ]);

        $this->billing->recordManualPayment(
            $invoice,
            $data['amount_cents'],
            $data['reference'] ?? null,
            $data['notes'] ?? null,
        );

        $this->audit->log('invoice.payment_recorded', MexcoInvoice::class, (string) $invoice->id, null, [
            'amount_cents' => $data['amount_cents'],
            'reference' => $data['reference'] ?? null,
        ]);

        return back()->with('success', 'Payment recorded.');
    }
}
