<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\CashTransaction;
use App\Models\Currency;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\Purchase;
use App\Models\Supplier;
use App\Models\SupplierPayment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class PaymentController extends Controller
{
    public function index()
    {
        return view('payments.index', [
            'customerInvoices' => Invoice::with('customer')->where('due_amount', '>', 0)->where('status', '!=', 'cancelled')->latest('invoice_date')->get(),
            'supplierPurchases' => Purchase::with('supplier')->where('due_amount', '>', 0)->latest('purchase_date')->get(),
            'customers' => Customer::orderBy('name')->get(),
            'suppliers' => Supplier::orderBy('name')->get(),
            'receipts' => Payment::with(['customer', 'invoice'])->latest('payment_date')->limit(12)->get(),
            'supplierPayments' => SupplierPayment::with(['supplier', 'purchase'])->latest('payment_date')->limit(12)->get(),
            'currencies' => Currency::where('is_active', true)->orderByDesc('is_default')->get(),
            'generalTransactions' => CashTransaction::latest('transaction_date')->limit(12)->get(),
        ]);
    }

    public function receive(Request $request)
    {
        $data = $request->validate(['invoice_id' => ['required', 'exists:invoices,id'], 'amount' => ['required', 'numeric', 'gt:0'], 'method' => ['required', 'in:cash,bank,mobile,other'], 'payment_date' => ['required', 'date'], 'reference' => ['nullable', 'string', 'max:100']]);
        $invoice = Invoice::lockForUpdate()->findOrFail($data['invoice_id']);
        if ($data['amount'] > $invoice->due_amount) return back()->withErrors(['amount' => __('Amount is greater than invoice due.')]);
        DB::transaction(function () use ($data, $invoice) { Payment::create($data + ['customer_id' => $invoice->customer_id, 'currency_code' => $invoice->currency_code]); $invoice->increment('paid_amount', $data['amount']); $invoice->decrement('due_amount', $data['amount']); $invoice->refresh(); $invoice->update(['status' => $invoice->due_amount <= 0 ? 'paid' : 'partial']); });
        return back()->with('success', __('Payment received from customer.'));
    }

    public function paySupplier(Request $request)
    {
        $data = $request->validate(['purchase_id' => ['required', 'exists:purchases,id'], 'amount' => ['required', 'numeric', 'gt:0'], 'method' => ['required', 'in:cash,bank,mobile,other'], 'payment_date' => ['required', 'date'], 'reference' => ['nullable', 'string', 'max:100']]);
        $purchase = Purchase::lockForUpdate()->findOrFail($data['purchase_id']);
        if (! $purchase->supplier_id) return back()->withErrors(['purchase_id' => __('The selected purchase has no supplier.')]);
        if ($data['amount'] > $purchase->due_amount) return back()->withErrors(['amount' => __('Amount is greater than purchase due.')]);
        DB::transaction(function () use ($data, $purchase) { SupplierPayment::create($data + ['supplier_id' => $purchase->supplier_id, 'currency_code' => $purchase->currency_code]); $purchase->increment('paid_amount', $data['amount']); $purchase->decrement('due_amount', $data['amount']); $purchase->refresh(); $purchase->update(['status' => $purchase->due_amount <= 0 ? 'paid' : 'partial']); });
        return back()->with('success', __('Supplier payment saved.'));
    }

    public function general(Request $request)
    {
        $data = $request->validate(['type' => ['required', 'in:receipt,payment'], 'party_name' => ['nullable', 'string', 'max:120'], 'category' => ['required', 'string', 'max:80'], 'amount' => ['required', 'numeric', 'gt:0'], 'currency_code' => ['required', 'exists:currencies,code'], 'method' => ['required', 'in:cash,bank,mobile,other'], 'transaction_date' => ['required', 'date'], 'reference' => ['nullable', 'string', 'max:100'], 'notes' => ['nullable', 'string']]);
        CashTransaction::create($data);
        return back()->with('success', $data['type'] === 'receipt' ? __('General receipt recorded.') : __('General payment recorded.'));
    }
}
