<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\Invoice;
use App\Models\InvoiceItem;
use App\Models\Setting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class InvoiceController extends Controller
{
    public function index(Request $request)
    {
        $invoices = Invoice::with('customer')
            ->when($request->search, fn($q, $s) =>
                $q->where('invoice_number', 'like', "%{$s}%")
                  ->orWhereHas('customer', fn($cq) => $cq->where('name', 'like', "%{$s}%")))
            ->when($request->status, fn($q, $s) => $q->where('status', $s))
            ->when($request->date_from, fn($q, $d) => $q->whereDate('invoice_date', '>=', $d))
            ->when($request->date_to, fn($q, $d) => $q->whereDate('invoice_date', '<=', $d))
            ->latest()
            ->paginate(15)
            ->withQueryString();

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

    public function create()
    {
        $customers = Customer::orderBy('name')->get();
        $taxRate   = Setting::getValue('tax_rate', 11);
        $number    = Invoice::generateNumber();

        return view('invoices.create', compact('customers', 'taxRate', 'number'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'customer_id'   => 'required|exists:customers,id',
            'invoice_date'  => 'required|date',
            'due_date'      => 'nullable|date|after_or_equal:invoice_date',
            'status'        => 'required|in:draft,sent,paid,cancelled',
            'discount'      => 'nullable|numeric|min:0',
            'tax'           => 'nullable|numeric|min:0',
            'shipping_cost' => 'nullable|numeric|min:0',
            'amount_paid'   => 'nullable|numeric|min:0',
            'notes'         => 'nullable|string',
            'items'         => 'required|array|min:1',
            'items.*.description' => 'required|string',
            'items.*.quantity'    => 'required|numeric|min:0.01',
            'items.*.unit_price'  => 'required|numeric|min:0',
        ]);

        DB::transaction(function () use ($request) {
            $invoice = Invoice::create([
                'invoice_number' => Invoice::generateNumber(),
                'customer_id'    => $request->customer_id,
                'invoice_date'   => $request->invoice_date,
                'due_date'       => $request->due_date,
                'status'         => $request->status,
                'discount'       => $request->discount ?? 0,
                'tax'            => $request->tax ?? 0,
                'shipping_cost'  => $request->shipping_cost ?? 0,
                'amount_paid'    => $request->amount_paid ?? 0,
                'notes'          => $request->notes,
                'subtotal'       => 0,
                'total'          => 0,
            ]);

            foreach ($request->items as $i => $item) {
                $invoice->items()->create([
                    'service_type' => $item['service_type'] ?? null,
                    'description' => $item['description'],
                    'quantity'    => $item['quantity'],
                    'unit'        => $item['unit'] ?? null,
                    'unit_price'  => $item['unit_price'],
                    'sort_order'  => $i,
                ]);
            }

            $invoice->recalculate();
            $this->storeRequest = $invoice; // temporary for redirect
        });

        return redirect()->route('invoices.index')
            ->with('success', 'Invoice berhasil dibuat.');
    }

    public function show(Invoice $invoice)
    {
        $invoice->load(['customer', 'items', 'receipt']);
        $settings = [
            'business_name'    => Setting::getValue('business_name'),
            'business_address' => Setting::getValue('business_address'),
            'business_phone'   => Setting::getValue('business_phone'),
            'signature_path'   => Setting::getValue('signature_path'),
            'stamp_path'       => Setting::getValue('stamp_path'),
        ];

        return view('invoices.show', compact('invoice', 'settings'));
    }

    public function edit(Invoice $invoice)
    {
        if ($invoice->status === 'paid') {
            return back()->with('error', 'Invoice yang sudah lunas tidak bisa diedit.');
        }

        $invoice->load('items');
        $customers = Customer::orderBy('name')->get();
        $taxRate   = Setting::getValue('tax_rate', 11);

        return view('invoices.edit', compact('invoice', 'customers', 'taxRate'));
    }

    public function update(Request $request, Invoice $invoice)
    {
        if ($invoice->status === 'paid') {
            return back()->with('error', 'Invoice yang sudah lunas tidak bisa diedit.');
        }

        $request->validate([
            'customer_id'   => 'required|exists:customers,id',
            'invoice_date'  => 'required|date',
            'due_date'      => 'nullable|date|after_or_equal:invoice_date',
            'status'        => 'required|in:draft,sent,paid,cancelled',
            'discount'      => 'nullable|numeric|min:0',
            'tax'           => 'nullable|numeric|min:0',
            'shipping_cost' => 'nullable|numeric|min:0',
            'amount_paid'   => 'nullable|numeric|min:0',
            'notes'         => 'nullable|string',
            'items'         => 'required|array|min:1',
            'items.*.description' => 'required|string',
            'items.*.quantity'    => 'required|numeric|min:0.01',
            'items.*.unit_price'  => 'required|numeric|min:0',
        ]);

        DB::transaction(function () use ($request, $invoice) {
            $invoice->update([
                'customer_id'   => $request->customer_id,
                'invoice_date'  => $request->invoice_date,
                'due_date'      => $request->due_date,
                'status'        => $request->status,
                'discount'      => $request->discount ?? 0,
                'tax'           => $request->tax ?? 0,
                'shipping_cost' => $request->shipping_cost ?? 0,
                'amount_paid'   => $request->amount_paid ?? 0,
                'notes'         => $request->notes,
            ]);

            $invoice->items()->delete();

            foreach ($request->items as $i => $item) {
                $invoice->items()->create([
                    'service_type' => $item['service_type'] ?? null,
                    'description'  => $item['description'],
                    'quantity'     => $item['quantity'],
                    'unit'         => $item['unit'] ?? null,
                    'unit_price'   => $item['unit_price'],
                    'sort_order'   => $i,
                ]);
            }

            $invoice->recalculate();
        });

        return redirect()->route('invoices.show', $invoice)
            ->with('success', 'Invoice berhasil diperbarui.');
    }

    public function destroy(Invoice $invoice)
    {
        if ($invoice->status === 'paid') {
            return back()->with('error', 'Invoice yang sudah lunas tidak bisa dihapus.');
        }

        $invoice->delete();

        return redirect()->route('invoices.index')
            ->with('success', 'Invoice berhasil dihapus.');
    }

    /**
     * Upload TTD & Stempel khusus untuk invoice ini
     */
    public function uploadAssets(Request $request, Invoice $invoice)
    {
        $request->validate([
            'signature' => 'nullable|image|max:2048',
            'stamp'     => 'nullable|image|max:2048',
        ]);

        if ($request->hasFile('signature')) {
            if ($invoice->signature_path) Storage::delete($invoice->signature_path);
            $invoice->signature_path = $request->file('signature')->store('signatures', 'public');
        }

        if ($request->hasFile('stamp')) {
            if ($invoice->stamp_path) Storage::delete($invoice->stamp_path);
            $invoice->stamp_path = $request->file('stamp')->store('stamps', 'public');
        }

        $invoice->save();

        return back()->with('success', 'TTD/Stempel berhasil diupload.');
    }

    /**
     * Cetak invoice (print-friendly view)
     */
    public function print(Invoice $invoice)
    {
        $invoice->load(['customer', 'items']);
        $settings = [
            'business_name'    => Setting::getValue('business_name'),
            'business_address' => Setting::getValue('business_address'),
            'business_phone'   => Setting::getValue('business_phone'),
            'business_email'   => Setting::getValue('business_email'),
            'business_website' => Setting::getValue('business_website'),
            'signature_path'   => $invoice->signature_path ?? Setting::getValue('signature_path'),
            'stamp_path'       => $invoice->stamp_path ?? Setting::getValue('stamp_path'),
        ];

        return view('invoices.print', compact('invoice', 'settings'));
    }

    /**
     * Laporan rekap invoice
     */
    public function report(Request $request)
    {
        $query = Invoice::with('customer')
            ->when($request->date_from, fn($q, $d) => $q->whereDate('invoice_date', '>=', $d))
            ->when($request->date_to, fn($q, $d) => $q->whereDate('invoice_date', '<=', $d))
            ->when($request->status, fn($q, $s) => $q->where('status', $s));

        $invoices = $query->latest()->paginate(20)->withQueryString();

        $summary = Invoice::query()
            ->when($request->date_from, fn($q, $d) => $q->whereDate('invoice_date', '>=', $d))
            ->when($request->date_to, fn($q, $d) => $q->whereDate('invoice_date', '<=', $d))
            ->when($request->status, fn($q, $s) => $q->where('status', $s))
            ->selectRaw('
                COUNT(*) as total_invoices,
                SUM(total) as total_amount,
                SUM(CASE WHEN status = "paid" THEN total ELSE 0 END) as total_paid,
                SUM(CASE WHEN status != "paid" THEN total ELSE 0 END) as total_unpaid
            ')
            ->first();

        return view('reports.invoices', compact('invoices', 'summary'));
    }
}
