<?php

namespace App\Http\Controllers;

use App\Models\PaymentModeModel;
use App\Models\PaymentStatusModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\InvoiceModel;
use App\Models\PaymentsModel;
use Illuminate\Http\Request;

class InvoicePaymentController extends Controller
{

    public function index()
    {
        $payments_data = InvoiceModel::with('payments', 'client.user')->where('branch_id', session('branch_id'))->where('oprntl_flag', 'A')
            ->has('payments')->orderBy('id', 'desc')->get();

        $status = PaymentStatusModel::all();

        return view('invoice-payments.index', compact('payments_data', 'status'));
    }

    public function add()
    {
        $invoices = InvoiceModel::where('branch_id', session('branch_id'))->doesntHave('payments')->where('oprntl_flag', 'A')->get();

        $payment_mode = PaymentModeModel::get();

        return view('invoice-payments.add', compact('invoices', 'payment_mode'));
    }

    public function getInvoiceDetails($id)
    {
        $invoice = InvoiceModel::find($id);
        if ($invoice) {
            return response()->json([
                'dueAmount' => round($invoice->final_amount, 2),
                'totalAmount' => round($invoice->final_amount, 2)
            ]);
        }
        return response()->json(['error' => 'Invoice not found'], 404);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'invoice' => 'required|exists:invoices,id',
            'paymentMethod' => 'required',
            'amount' => 'required|numeric|min:0.01',
            'paymentDate' => 'required|date',
            'note' => 'nullable|string',
        ]);

        DB::beginTransaction();

        try {
            $invoice = InvoiceModel::find($validated['invoice']);
            if (!$invoice) {
                throw new \Exception('Invoice not found');
            }

            $payment = PaymentsModel::create([
                'invoice_id' => $validated['invoice'],
                'payment_mode' => $validated['paymentMethod'],
                'total_amount' => $invoice->final_amount,
                'amount' => $validated['amount'],
                'payment_date' => $validated['paymentDate'],
                'notes' => $validated['note'] ?? null,
            ]);

            $dueAmount = $invoice->final_amount;
            $status = $this->determinePaymentStatus($validated['amount'], $dueAmount);

            $paymentStatus = DB::table('payment_status')->where('name', $status)->first();
            if (!$paymentStatus) {
                throw new \Exception('Payment status not found');
            }

            $invoice->update([
                'status' => $paymentStatus->id,
                'updated_at' => now(),
            ]);

            DB::commit();

            return redirect()->route('invoice-payment-index')
                ->with('success', 'Payment created successfully!');

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Payment creation failed: ' . $e->getMessage(), ['request' => $request->all()]);

            return back()->withInput()
                ->with('error', 'Payment creation failed, Please try again');
        }
    }

    public function edit($id)
    {
        $invoice = InvoiceModel::findOrFail($id);

        $payment = PaymentsModel::where('invoice_id', $id)->first();

        $totalPaidAmount = PaymentsModel::where('invoice_id', $id)->sum('amount');

        $dueAmount = round($invoice->final_amount - $totalPaidAmount, 2);

        $paymentsForInvoice = PaymentsModel::where('invoice_id', $id)->get();

        $payment_mode = PaymentModeModel::get();


        return view('invoice-payments.edit', compact('invoice', 'payment', 'totalPaidAmount', 'dueAmount', 'paymentsForInvoice', 'payment_mode'));
    }

    public function update(Request $request)
    {
        $validated = $request->validate([
            'invoice' => 'required|exists:invoices,id',
            'paymentMethod' => 'required',
            'amount' => 'required|numeric|min:0.01',
            'paymentDate' => 'required|date',
            'note' => 'nullable|string',
            'paidAmount' => 'nullable|numeric',
            'totalAmount' => 'nullable|numeric',
        ]);

        $newPaidAmount = (float) $validated['paidAmount'] + (float) $validated['amount'];

        if ($newPaidAmount > (float) $validated['totalAmount']) {
            return back()->withInput()
                ->with('error', 'Payment amount cannot exceed the total due amount. Please try again!');
        }

        DB::beginTransaction();

        try {
            PaymentsModel::create([
                'invoice_id' => $validated['invoice'],
                'payment_mode' => $validated['paymentMethod'],
                'total_amount' => $validated['totalAmount'],
                'amount' => $validated['amount'],
                'payment_date' => $validated['paymentDate'],
                'notes' => $validated['note'] ?? null,
            ]);

            $paidAmount = PaymentsModel::where('invoice_id', $validated['invoice'])->sum('amount');
            $invoice = InvoiceModel::find($validated['invoice']);

            if ($invoice) {
                $status = $this->determinePaymentStatus($paidAmount, $invoice->final_amount);
                $paymentStatus = DB::table('payment_status')->where('name', $status)->first();

                $invoice->update([
                    'status' => $paymentStatus->id,
                    'updated_at' => now(),
                ]);
            }

            DB::commit();

            return redirect()->route('invoice-payment-index')
                ->with('success', 'Payment updated and a new record created successfully!');

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Payment update failed: ' . $e->getMessage(), ['request' => $request->all()]);

            return back()->withInput()
                ->with('error', 'Payment update failed, Please try again.');
        }
    }

    public function delete($id)
    {
        DB::beginTransaction();

        try {
            $payments = PaymentsModel::where('invoice_id', $id)->first();

            if (!$payments) {
                throw new \Exception('Payments not found');
            }

            $invoiceId = $payments->invoice_id;
            $invoice = InvoiceModel::find($invoiceId);

            if ($invoice) {
                $invoice->status = '1';
                $invoice->save();
            }

            PaymentsModel::where('invoice_id', $invoiceId)->delete();

            DB::commit();
            return redirect()->route('invoice-payment-index')
                ->with('success', 'Payments deleted successfully!');

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Payments deletion failed: ' . $e->getMessage(), ['invoice_id' => $id]);

            return back()->withInput()
                ->with('error', 'Payments deletion failed: ' . $e->getMessage());
        }
    }

    protected function determinePaymentStatus($paidAmount, $totalAmount)
    {
        if ($paidAmount >= $totalAmount) {
            return 'Paid';
        } elseif ($paidAmount > 0 && $paidAmount < $totalAmount) {
            return 'Partially Paid';
        } else {
            return 'Unpaid';
        }
    }
}