<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\CreditNote;
use App\Models\LegalCase; // <--- Imported LegalCase
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class FinanceController extends Controller
{
    public function index()
    {
        // 1. Dashboard Metrics
        $totalInvoiced = Invoice::sum('total_amount');
        $totalCollected = Payment::sum('amount');
        $totalCredited = CreditNote::sum('amount');
        $outstanding = $totalInvoiced - ($totalCollected + $totalCredited);

        // 2. Data for Dropdowns & Tables

        // Fetch Payments for "Recent Transactions" table
        $payments = Payment::with('invoice.case.client')
            ->latest()
            ->take(10) // Match the "Last 10 Records" label in view
            ->get();

        // Fetch Invoices for "Record Payment" & "Credit Note" dropdowns
        // We generally want unpaid invoices, but for credit notes we might need paid ones too.
        // Let's get all active invoices.
        $invoices = Invoice::with('case.client')
            ->where('status', '!=', 'paid') // Focus on ones needing action
            ->orWhere('updated_at', '>=', now()->subDays(30)) // Plus recently paid ones
            ->latest()
            ->get();

        // [NEW] Fetch Cases for the "Quick Invoice" dropdown
        $cases = LegalCase::with('client')
            ->where('status', '!=', 'closed')
            ->latest()
            ->get();

        return view('admin.finance.index', compact(
            'totalInvoiced',
            'totalCollected',
            'totalCredited',
            'outstanding',
            'payments',
            'invoices',
            'cases' // <--- Passed to view
        ));
    }

    // [NEW] GENERATE QUICK INVOICE
    public function quickInvoice(Request $request)
    {
        $request->validate([
            'case_id' => 'required|exists:legal_cases,id',
            'description' => 'required|string|max:255',
            'amount' => 'required|numeric|min:1',
            'due_date' => 'required|date',
        ]);

        // 1. Generate Invoice Number (Format: INV-2026-0001)
        $year = date('Y');
        $nextId = Invoice::count() + 1;
        $invNum = 'INV-' . $year . '-' . str_pad($nextId, 4, '0', STR_PAD_LEFT);

        // 2. Create the Invoice Parent
        $invoice = Invoice::create([
            'legal_case_id' => $request->case_id,
            'invoice_number' => $invNum,
            'due_date' => $request->due_date,
            'subtotal' => $request->amount,
            'tax' => 0, // Quick invoices usually inclusive, or set logic here
            'total_amount' => $request->amount,
            'status' => 'unpaid',
            'user_id' => auth()->id(), // Track creator
        ]);

        // 3. Create the Line Item (Assuming you have an items relationship)
        // If you don't have an InvoiceItem model yet, you can skip this,
        // but typically invoices have items.
        if (method_exists($invoice, 'items')) {
            $invoice->items()->create([
                'description' => $request->description,
                'amount' => $request->amount,
                'quantity' => 1
            ]);
        }

        // 4. Log Activity (Optional)
        if (class_exists('\App\Models\ActivityLog')) {
            \App\Models\ActivityLog::record('Finance', 'Invoice', "Generated Quick Invoice #{$invNum}");
        }

        return back()->with('success', 'Invoice generated successfully.');
    }

    // RECORD A PAYMENT
    public function storePayment(Request $request)
    {
        try {
            $request->validate([
                'amount' => 'required|numeric|min:1',
                'payment_date' => 'required|date',
                'method' => 'required',
                'chart_of_account_id' => 'required|exists:chart_of_accounts,id',

                'invoice_id' => 'nullable|exists:invoices,id',

                // FIX IS HERE: Added 'nullable' to ignore empty strings from hidden fields
                'client_id' => 'nullable|required_without:invoice_id|exists:users,id',

                'transaction_ref' => 'nullable|string'
            ]);

            $clientId = $request->client_id;
            $invoice = null;

            // 2. Scenario A: Paying an Invoice
            if ($request->invoice_id) {
                $invoice = \App\Models\Invoice::with('case.client')->findOrFail($request->invoice_id);

                // Safety check: Ensure the invoice actually has a linked client
                if (!$invoice->case || !$invoice->case->client) {
                    return back()->with('error', 'The selected invoice is not linked to a valid client/case.');
                }

                $clientId = $invoice->case->client->id; // Overwrite form input with actual invoice client

                // Prevent overpayment on invoices
                if ($request->amount > $invoice->balance) {
                    return back()->with('error', 'Payment amount exceeds invoice balance.');
                }
            }

            // 3. Record the Payment
            \App\Models\Payment::create([
                'invoice_id' => $request->invoice_id,
                'client_id' => $clientId,
                'chart_of_account_id' => $request->chart_of_account_id,
                'amount' => $request->amount,
                'payment_date' => $request->payment_date,
                'method' => $request->method,
                'transaction_ref' => $request->transaction_ref,
            ]);

            // 4. Auto-update Invoice Status
            if ($invoice && $invoice->refresh()->balance <= 0) {
                $invoice->update(['status' => 'paid']);
            }

            return back()->with('success', 'Transaction recorded and ledger updated.');
        } catch (\Exception $e) {
            \Log::error(["Error saving transaction" => $e->getMessage()]);
            // It's often better to show the actual validation error if possible,
            // but for generic exceptions:
            return back()->with('error', 'Error recording transaction: ' . $e->getMessage());
        }
    }


    // public function storePayment(Request $request)
    // {
    //     $request->validate([
    //         'invoice_id' => 'required|exists:invoices,id',
    //         'amount' => 'required|numeric|min:1',
    //         'payment_date' => 'required|date',
    //         'method' => 'required',
    //         'transaction_ref' => 'nullable|string'

    //     ]);

    //     $invoice = Invoice::findOrFail($request->invoice_id);

    //     // Prevent overpayment
    //     if ($request->amount > $invoice->balance) {
    //         return back()->with('error', 'Payment amount exceeds invoice balance.');
    //     }

    //     Payment::create([
    //         'invoice_id' => $request->invoice_id,
    //         'amount' => $request->amount,
    //         'payment_date' => $request->payment_date,
    //         'method' => $request->method,
    //         'transaction_ref' => $request->transaction_ref,
    //     ]);

    //     // Auto-update Invoice Status
    //     if ($invoice->refresh()->balance <= 0) {
    //         $invoice->update(['status' => 'paid']);
    //     }

    //     return back()->with('success', 'Payment recorded successfully.');
    // }

    // ISSUE CREDIT NOTE
    public function storeCreditNote(Request $request)
    {
        $request->validate([
            'invoice_id' => 'required|exists:invoices,id',
            'amount' => 'required|numeric|min:1',
            'reason' => 'required|string',
        ]);

        $invoice = Invoice::findOrFail($request->invoice_id);

        CreditNote::create([
            'invoice_id' => $invoice->id,
            'credit_number' => 'CN-' . strtoupper(Str::random(6)),
            'amount' => $request->amount,
            'issued_date' => now(),
            'reason' => $request->reason,
        ]);

        // Check if fully settled after credit
        if ($invoice->refresh()->balance <= 0) {
            $invoice->update(['status' => 'paid']);
        }

        return back()->with('success', 'Credit Note issued.');
    }


    // Display the Accounts
    public function accounts()
    {
        $accounts = \App\Models\ChartOfAccount::orderBy('code')->get()->groupBy('type');
        return view('admin.finance.accounts', compact('accounts'));
    }

    // Store a new Account
    public function storeAccount(Request $request)
    {
        $request->validate([
            'name' => 'required|string',
            'type' => 'required|in:income,expense,asset,liability,equity',
            'code' => 'nullable|string|unique:chart_of_accounts,code'
        ]);

        \App\Models\ChartOfAccount::create($request->all());

        return back()->with('success', 'Account added to Chart.');
    }


    // chart of accounts

    // --- CHART OF ACCOUNTS MANAGEMENT ---

    // public function accounts()
    // {
    //     // Get all accounts grouped by type for the view
    //     $accounts = \App\Models\ChartOfAccount::orderBy('code')->get()->groupBy('type');
    //     return view('admin.finance.accounts', compact('accounts'));
    // }

    // public function storeAccount(Request $request)
    // {
    //     $request->validate([
    //         'name' => 'required|string|max:255',
    //         'type' => 'required|in:income,expense,asset,liability,equity',
    //         'code' => 'nullable|string|unique:chart_of_accounts,code',
    //         'description' => 'nullable|string'
    //     ]);

    //     \App\Models\ChartOfAccount::create($request->all());

    //     return back()->with('success', 'New ledger account created.');
    // }

    public function updateAccount(Request $request, $id)
    {
        $account = \App\Models\ChartOfAccount::findOrFail($id);

        $request->validate([
            'name' => 'required|string|max:255',
            'code' => 'nullable|string|unique:chart_of_accounts,code,' . $account->id, // Ignore self
            'description' => 'nullable|string'
        ]);

        // Prevent changing type if transactions exist (Data Integrity)
        if ($account->payments()->exists() && $request->type !== $account->type) {
            return back()->with('error', 'Cannot change Account Type because it has existing transactions.');
        }

        $account->update($request->all());

        return back()->with('success', 'Account details updated.');
    }

    public function destroyAccount($id)
    {
        $account = \App\Models\ChartOfAccount::findOrFail($id);

        // Safety Check: Do not delete if used
        if ($account->payments()->exists()) {
            return back()->with('error', 'Cannot delete this account because it has recorded transactions. Archive it instead.');
        }

        $account->delete();

        return back()->with('success', 'Account deleted successfully.');
    }

    public function listAll()
    {
        // Added 'payments' to the eager load list
        $invoices = Invoice::with(['case.client', 'payments'])->latest()->paginate(10, ['*'], 'invoices');

        $expenses = Payment::whereHas('account', function ($q) {
            $q->where('type', 'expense');
        })->with(['account', 'client'])->latest()->paginate(10, ['*'], 'expenses');

        return view('admin.finance.ledger', compact('invoices', 'expenses'));
    }

    public function updateInvoice(Request $request, $id)
    {
        $invoice = Invoice::findOrFail($id);

        $request->validate([
            'amount' => 'required|numeric|min:0',
            'status' => 'required|in:unpaid,paid,overdue,partially_paid',
        ]);

        // Safety Check: If they lower the amount below what has already been paid
        $totalPaid = $invoice->payments()->sum('amount');
        if ($request->amount < $totalPaid) {
            return back()->with('error', "Cannot set invoice total to KES " . number_format($request->amount) . " because KES " . number_format($totalPaid) . " has already been paid.");
        }

        $invoice->update([
            'total_amount' => $request->amount,
            'status' => $request->status,
        ]);

        // Log the change for audit purposes
        Log::info("Invoice #{$invoice->invoice_number} updated by User ID: " . auth()->id());

        return back()->with('success', 'Invoice updated successfully.');
    }

    /**
     * Update Expense (Payment) Details
     */
    public function updateExpense(Request $request, $id)
    {
        // Ensure we are only editing a payment that is actually an expense
        $expense = Payment::whereHas('account', function ($q) {
            $q->where('type', 'expense');
        })->findOrFail($id);

        $request->validate([
            'amount' => 'required|numeric|min:0',
            'transaction_ref' => 'nullable|string|max:255',
            'payment_date' => 'nullable|date',
        ]);

        $expense->update([
            'amount' => $request->amount,
            'transaction_ref' => $request->transaction_ref,
            'payment_date' => $request->payment_date ?? $expense->payment_date,
        ]);

        Log::info("Expense record ID: {$id} updated by User ID: " . auth()->id());

        return back()->with('success', 'Expense record updated.');
    }
}
