<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\JournalEntry;
use App\Models\JournalTransaction;
use App\Models\Account;
use App\Models\Customer;
use App\Models\Vendor;
use App\Models\Equipment;
use App\Models\Invoice;

class JournalEntryController extends Controller
{
    public function index()
    {
        $journals = JournalEntry::with(['transactions.account'])->get();
        return view('admin.journals.index', compact('journals'));
    }

    public function show($id)
    {
        $entry = JournalEntry::with('transactions')->findOrFail($id);
        return view('admin.journals.show', compact('entry'));
    }

    public function create()
    {
        $accounts = Account::all();
        $customers = Customer::all();
        $vendors = Vendor::all();
        $equipments = Equipment::all();
        $invoices = Invoice::whereIn('status', ['created', 'submitted'])->get();

        return view('admin.journals.create', compact('accounts', 'customers', 'vendors', 'equipments', 'invoices'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'date' => 'required|date',
            'description' => 'required|string',
            'transactions' => 'required|array|min:1',
            'transactions.*.debit_account_id' => 'nullable|exists:accounts,id',
            'transactions.*.credit_account_id' => 'nullable|exists:accounts,id',
            'transactions.*.debit' => 'nullable|numeric|min:0',
            'transactions.*.credit' => 'nullable|numeric|min:0',
        ]);

        $invoice = Invoice::where('invoice_number', $request->inv_id)->first();

        $journal = JournalEntry::create([
            'user_id' => auth()->id(),
            'date' => $request->date,
            'description' => $request->description,
            'allocation' => $request->allocation,
            'inv_id' => Invoice::find($request->inv_id)?->invoice_number ?? $request->inv_id,
            'inv_date' => $request->inv_date,
            'customer_id' => $request->customer_id,
            'vendor_id' => $request->vendor_id,
            'machine_id' => $request->equipment_id,
        ]);

        foreach ($request->transactions as $t) {
            if (!empty($t['debit_account_id']) && $t['debit'] > 0) {
                $journal->transactions()->create([
                    'user_id' => auth()->id(),
                    'account_id' => $t['debit_account_id'],
                    'debit' => $t['debit'],
                    'credit' => 0,
                    'description' => $t['description'] ?? null,
                ]);
            }

            if (!empty($t['credit_account_id']) && $t['credit'] > 0) {
                $journal->transactions()->create([
                    'user_id' => auth()->id(),
                    'account_id' => $t['credit_account_id'],
                    'debit' => 0,
                    'credit' => $t['credit'],
                    'description' => $t['description'] ?? null,
                ]);
            }
        }

        if ($invoice) {
            $existingRevenuePosted = JournalEntry::where('inv_id', $invoice->invoice_number)
                ->whereHas('transactions.account', fn($q) => $q->where('code', 4001)) // Generator Rentals
                ->exists();

            $totalDebits = collect($request->transactions)->sum(fn($t) => $t['debit'] ?? 0);
            $invoice->amount_paid += $totalDebits;

            if (!$invoice->is_recorded_in_journal && $existingRevenuePosted) {
                $invoice->is_recorded_in_journal = true;
            }

            $invoice->save();
        }

        return redirect()->route('admin.journals.index')->with('success', 'Journal entry posted.');
    }

    public function edit(JournalEntry $journal)
    {
        $accounts = Account::all();
        $customers = Customer::all();
        $vendors = Vendor::all();
        $equipments = Equipment::all();
        $journal->load('transactions');

        return view('admin.journals.create', compact('journal', 'accounts', 'customers', 'vendors', 'equipments'));
    }

    public function update(Request $request, JournalEntry $journal)
    {
        $request->validate([
            'date' => 'required|date',
            'description' => 'required|string',
            'transactions' => 'required|array|min:1',
            'transactions.*.debit_account_id' => 'nullable|exists:accounts,id',
            'transactions.*.credit_account_id' => 'nullable|exists:accounts,id',
            'transactions.*.debit' => 'nullable|numeric|min:0',
            'transactions.*.credit' => 'nullable|numeric|min:0',
        ]);

        $invoice = Invoice::where('invoice_number', $request->inv_id)->first();

        $journal->update([
            'date' => $request->date,
            'description' => $request->description,
            'allocation' => $request->allocation,
            'inv_id' => Invoice::find($request->inv_id)?->invoice_number ?? $request->inv_id,
            'inv_date' => $request->inv_date,
            'customer_id' => $request->customer_id,
            'vendor_id' => $request->vendor_id,
            'machine_id' => $request->equipment_id,
        ]);

        $journal->transactions()->delete();

        foreach ($request->transactions as $t) {
            if (!empty($t['debit_account_id']) && $t['debit'] > 0) {
                $journal->transactions()->create([
                    'user_id' => auth()->id(),
                    'account_id' => $t['debit_account_id'],
                    'debit' => $t['debit'],
                    'credit' => 0,
                    'description' => $t['description'] ?? null,
                ]);
            }

            if (!empty($t['credit_account_id']) && $t['credit'] > 0) {
                $journal->transactions()->create([
                    'user_id' => auth()->id(),
                    'account_id' => $t['credit_account_id'],
                    'debit' => 0,
                    'credit' => $t['credit'],
                    'description' => $t['description'] ?? null,
                ]);
            }
        }

        return redirect()->route('admin.journals.index')->with('success', 'Journal entry updated.');
    }

    public function destroy(JournalEntry $journal)
    {
        $journal->transactions()->delete();
        $journal->delete();

        return redirect()->route('admin.journals.index')->with('success', 'Journal entry deleted.');
    }

    public function createFromInvoice(Invoice $invoice)
    {
        $status = $invoice->status;

        $debitCodes = match ($status) {
            'submitted', 'partially_paid' => [1001, 1002, 1003, 1100],
            'paid'                        => [1001, 1100],
            default                       => [],
        };

        $creditCodes = [4001, 4002, 4003, 4004];

        $debitAccounts = Account::whereIn('code', $debitCodes)->get();
        $creditAccounts = Account::whereIn('code', $creditCodes)->get();

        return view('admin.journals.from_invoice_form', [
            'invoice' => $invoice,
            'status' => $status,
            'debitAccounts' => $debitAccounts,
            'creditAccounts' => $creditAccounts,
        ]);
    }
}
