<?php

namespace App\Http\Controllers;

use App\Models\Invoice;
use App\Services\InvoicePdfService;
use App\Services\InvoiceService;
use Illuminate\Http\Request;

class InvoiceController extends Controller
{
    public function __construct(
        protected InvoiceService $service,
        protected InvoicePdfService $pdfService
    ) {
        $this->middleware('permission:invoices.view')->only(['index', 'show']);
        $this->middleware('permission:invoices.edit')->only(['edit', 'update']);
        $this->middleware('permission:invoices.delete')->only(['destroy']);
        $this->middleware('permission:invoices.print')->only(['print', 'pdf', 'thermal']);
        $this->middleware('permission:invoices.cancel')->only(['cancel']);
    }

    public function index(Request $request)
    {
        $invoices = Invoice::query()
            ->with(['customer', 'line', 'items'])
            ->search($request->get('q'))
            ->when($request->status, fn ($q, $v) => $q->where('status', $v))
            ->latest('date')
            ->paginate(per_page())
            ->withQueryString();

        $shareTexts = [];
        foreach ($invoices as $invoice) {
            $shareTexts[$invoice->id] = $this->service->shareText($invoice);
        }

        return view('invoices.index', compact('invoices', 'shareTexts'));
    }

    public function show(Invoice $invoice)
    {
        $invoice->load(['customer', 'line', 'plan', 'items.billingPeriod', 'user', 'payments']);

        return view('invoices.show', [
            'invoice' => $invoice,
            'shareText' => $this->service->shareText($invoice),
        ]);
    }

    public function edit(Invoice $invoice)
    {
        return view('invoices.edit', compact('invoice'));
    }

    public function update(Request $request, Invoice $invoice)
    {
        $data = $request->validate([
            'date' => ['required', 'date'],
            'notes' => ['nullable', 'string', 'max:2000'],
        ]);

        $this->service->update($invoice, $data, $request->user());

        return redirect()->route('invoices.show', $invoice)->with('success', __('messages.updated'));
    }

    public function destroy(Request $request, Invoice $invoice)
    {
        $data = $request->validate([
            'reason' => ['nullable', 'string', 'max:255'],
        ]);

        $this->service->delete(
            $invoice,
            $request->user(),
            $data['reason'] ?: __('messages.deleted')
        );

        return redirect()->route('invoices.index')->with('success', __('messages.invoice_deleted'));
    }

    public function print(Invoice $invoice)
    {
        $invoice->load(['customer', 'line', 'plan', 'items.billingPeriod', 'user']);

        return view('invoices.print', [
            'invoice' => $invoice,
            'hideName' => request()->boolean('hide_name'),
        ]);
    }

    public function thermal(Invoice $invoice)
    {
        $invoice->load(['customer', 'line', 'plan', 'items.billingPeriod']);

        return view('invoices.thermal', [
            'invoice' => $invoice,
            'hideName' => request()->boolean('hide_name'),
        ]);
    }

    public function pdf(Invoice $invoice)
    {
        return $this->pdfService->download($invoice, request()->boolean('hide_name'));
    }

    public function cancel(Request $request, Invoice $invoice)
    {
        $data = $request->validate(['reason' => ['required', 'string', 'max:255']]);
        $this->service->cancel($invoice, $request->user(), $data['reason']);

        return back()->with('success', __('messages.invoice_cancelled'));
    }
}
