<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreQuoteRequest;
use App\Models\AuditLog;
use App\Models\Quote;
use App\Models\User;
use App\Notifications\QuoteSentNotification;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Notification;
use Inertia\Inertia;
use Inertia\Response;

class QuoteController extends Controller
{
    public function index(Request $request): Response
    {
        $query = Quote::query()
            ->with(['user:id,name,email', 'creator:id,name,email']);

        if ($search = $request->input('search')) {
            $query->where(function ($q) use ($search): void {
                $q->where('number', 'like', "%{$search}%")
                    ->orWhere('prospect_email', 'like', "%{$search}%")
                    ->orWhere('prospect_name', '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);
        }

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

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

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

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

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

        $items = $validated['items'];
        $subtotal = collect($items)->sum(fn (array $item): float => (float) $item['unit_price'] * (int) $item['quantity']);
        $tax = (float) ($validated['tax'] ?? 0);
        $total = $subtotal + $tax;

        $quote = Quote::create([
            'user_id' => $validated['user_id'] ?? null,
            'prospect_email' => $validated['prospect_email'] ?? null,
            'prospect_name' => $validated['prospect_name'] ?? null,
            'number' => Quote::generateNumber(),
            'status' => 'draft',
            'items' => $items,
            'subtotal' => $subtotal,
            'tax' => $tax,
            'total' => $total,
            'currency' => $validated['currency'],
            'notes' => $validated['notes'] ?? null,
            'valid_until' => $validated['valid_until'] ?? null,
            'created_by' => $request->user()->id,
        ]);

        AuditLog::create([
            'admin_id' => $request->user()?->id,
            'action' => 'create_quote',
            'resource_type' => 'quote',
            'resource_id' => $quote->id,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'changes' => ['total' => $total, 'items_count' => count($items)],
        ]);

        return redirect()->route('admin.quotes.show', $quote)
            ->with('success', "Quote {$quote->number} has been created.");
    }

    public function show(Quote $quote): Response
    {
        $quote->load(['user:id,name,email', 'creator:id,name,email']);

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

    public function edit(Quote $quote): Response
    {
        $quote->load(['user:id,name,email']);

        $customers = User::query()
            ->select('id', 'name', 'email')
            ->orderBy('name')
            ->get();

        return Inertia::render('Admin/Quotes/Edit', [
            'quote' => $quote,
            'customers' => $customers,
        ]);
    }

    public function update(StoreQuoteRequest $request, Quote $quote): RedirectResponse
    {
        if (in_array($quote->status, ['accepted', 'rejected'])) {
            return redirect()->back()->with('error', 'Cannot edit a quote that has been accepted or rejected.');
        }

        $validated = $request->validated();

        $items = $validated['items'];
        $subtotal = collect($items)->sum(fn (array $item): float => (float) $item['unit_price'] * (int) $item['quantity']);
        $tax = (float) ($validated['tax'] ?? 0);
        $total = $subtotal + $tax;

        $quote->update([
            'user_id' => $validated['user_id'] ?? null,
            'prospect_email' => $validated['prospect_email'] ?? null,
            'prospect_name' => $validated['prospect_name'] ?? null,
            'items' => $items,
            'subtotal' => $subtotal,
            'tax' => $tax,
            'total' => $total,
            'currency' => $validated['currency'],
            'notes' => $validated['notes'] ?? null,
            'valid_until' => $validated['valid_until'] ?? null,
        ]);

        AuditLog::create([
            'admin_id' => $request->user()?->id,
            'action' => 'update_quote',
            'resource_type' => 'quote',
            'resource_id' => $quote->id,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'changes' => ['total' => $total],
        ]);

        return redirect()->route('admin.quotes.show', $quote)
            ->with('success', "Quote {$quote->number} has been updated.");
    }

    public function destroy(Request $request, Quote $quote): RedirectResponse
    {
        if (in_array($quote->status, ['accepted'])) {
            return redirect()->back()->with('error', 'Cannot delete an accepted quote.');
        }

        $number = $quote->number;
        $quoteId = $quote->id;
        $quote->delete();

        AuditLog::create([
            'admin_id' => $request->user()?->id,
            'action' => 'delete_quote',
            'resource_type' => 'quote',
            'resource_id' => $quoteId,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'changes' => ['number' => $number],
        ]);

        return redirect()->route('admin.quotes.index')
            ->with('success', "Quote {$number} has been deleted.");
    }

    public function send(Request $request, Quote $quote): RedirectResponse
    {
        $recipientEmail = $quote->getRecipientEmail();

        if (! $recipientEmail) {
            return redirect()->back()->with('error', 'No recipient email found for this quote.');
        }

        $signedUrl = \Illuminate\Support\Facades\URL::signedRoute('quotes.show', ['quote' => $quote->id]);

        if ($quote->user) {
            $quote->user->notify(new QuoteSentNotification($quote, $signedUrl));
        } else {
            Notification::route('mail', $recipientEmail)
                ->notify(new QuoteSentNotification($quote, $signedUrl));
        }

        $quote->markSent();

        AuditLog::create([
            'admin_id' => $request->user()?->id,
            'action' => 'send_quote',
            'resource_type' => 'quote',
            'resource_id' => $quote->id,
            'ip_address' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'changes' => ['sent_to' => $recipientEmail],
        ]);

        return redirect()->back()
            ->with('success', "Quote {$quote->number} has been sent to {$recipientEmail}.");
    }

    public function download(Quote $quote): \Symfony\Component\HttpFoundation\Response
    {
        $quote->load(['user', 'creator']);

        $pdf = Pdf::loadView('pdf.quote', ['quote' => $quote]);

        return $pdf->download("quote-{$quote->number}.pdf");
    }
}
