<?php

namespace App\Http\Controllers;

use App\Models\Currency;
use App\Models\Project;
use App\Models\GeneralJournalTemp;
use App\Models\GeneralJournal;
use App\Services\MainAccountPickerService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class GeneralJournalController extends Controller
{
    public function index()
    {
        $currencies = Currency::all();
        $projects = Project::orderBy('name')->get();
        $accounts = app(MainAccountPickerService::class)->allMainAccounts();
        $tempEntries = GeneralJournalTemp::where('status', 'Pending')->get();

        return view('generalJournal.general-journal', compact(
            'currencies',
            'projects' ,
            'accounts',
            'tempEntries'
        ));
    }

    public function store(Request $request)
    {
        $request->validate([
            'date' => 'required|date',
            'account_id' => 'required|exists:main_accounts,id',
            'narration' => 'required|string|max:255',
            'reference' => 'required|string|max:100',
            'currency_id' => 'required|exists:currencies,id',
            'project_id' => 'nullable|exists:projects,id',
            'tr_code' => 'required|in:DR,CR',
            'amount' => 'required|numeric|min:0'
        ]);

        GeneralJournalTemp::create([
            'date' => $request->date,
            'account_id' => $request->account_id,
            'narration' => $request->narration,
            'reference' => $request->reference,
            'currency_id' => $request->currency_id,
            'project_id' => $request->project_id,
            'tr_code' => $request->tr_code,
            'amount' => $request->amount,
            'status' => 'Pending'
        ]);

        return redirect()->route('general.journal.index')
            ->with('success', 'Journal entry saved successfully!');
    }

    public function update(Request $request)
    {
        $request->validate([
            'id' => 'required|exists:general_journal_temps,id',
            'date' => 'required|date',
            'account_id' => 'required|exists:main_accounts,id',
            'narration' => 'required|string|max:255',
            'reference' => 'required|string|max:100',
            'currency_id' => 'required|exists:currencies,id',
            'project_id' => 'nullable|exists:projects,id',
            'tr_code' => 'required|in:DR,CR',
            'amount' => 'required|numeric|min:0'
        ]);

        $entry = GeneralJournalTemp::findOrFail($request->id);
        $entry->update($request->only([
            'date', 'account_id', 'narration', 'reference', 
            'currency_id', 'project_id' , 'tr_code', 'amount'
        ]));

        return redirect()->route('general.journal.index')
            ->with('success', 'Journal entry updated successfully!');
    }

    public function destroy($id)
    {
        $entry = GeneralJournalTemp::findOrFail($id);
        $entry->delete();

        return redirect()->route('general.journal.index')
            ->with('success', 'Entry deleted successfully!');
    }

    // ✅ Process a single entry only if its pair exists (amount + currency)
    public function processSingle($id)
    {
        $entry = GeneralJournalTemp::findOrFail($id);

        // Look for matching pair: same amount, same currency, opposite tr_code
        $pair = GeneralJournalTemp::where('amount', $entry->amount)
            ->where('currency_id', $entry->currency_id)
            ->where('tr_code', $entry->tr_code === 'DR' ? 'CR' : 'DR')
            ->where('status', 'Pending')
            ->first();

        if (!$pair) {
            return redirect()->route('general.journal.index')
                ->with('process_error', "Cannot process entry for account '{$entry->account->account_name}' (Amount: {$entry->amount}, Currency: {$entry->currency->code}) — No contra account found.");
        }

        DB::transaction(function () use ($entry, $pair) {
            // Process both entries
            GeneralJournal::create($entry->only([
                'date', 'account_id', 'narration', 'reference',
                'currency_id', 'tr_code', 'amount'
            ]));

            GeneralJournal::create($pair->only([
                'date', 'account_id', 'narration', 'reference',
                'currency_id', 'tr_code', 'amount'
            ]));

            // Remove from temp
            $entry->delete();
            $pair->delete();
        });

        return redirect()->route('general.journal.index')
            ->with('success', 'Journal entry and its pair processed successfully!');
    }

    // ✅ Process all entries only if all have pairs (amount + currency)
    public function process()
    {
        $tempEntries = GeneralJournalTemp::where('status', 'Pending')->get();
        $unpairedEntries = [];

        // Group entries by amount and currency
        $amountCurrencyGroups = $tempEntries->groupBy(function ($item) {
            return $item->amount . '_' . $item->currency_id;
        });

        foreach ($amountCurrencyGroups as $group) {
            $drCount = $group->where('tr_code', 'DR')->count();
            $crCount = $group->where('tr_code', 'CR')->count();

            if ($drCount !== $crCount) {
                foreach ($group as $entry) {
                    $unpairedEntries[] = $entry;
                }
            }
        }

        if (!empty($unpairedEntries)) {
            $msg = "Cannot process all entries. The following entries are imbalance: ";
            foreach ($unpairedEntries as $entry) {
                $msg .= "[Account: {$entry->account->account_name}, Amount: {$entry->amount}, Currency: {$entry->currency->code}, Type: {$entry->tr_code}] ";
            }

            return redirect()->route('general.journal.index')
                ->with('process_error', $msg);
        }

        // All entries have pairs, process all
        DB::transaction(function () use ($tempEntries) {
            foreach ($tempEntries as $entry) {
                GeneralJournal::create($entry->only([
                    'date', 'account_id', 'narration', 'reference',
                    'currency_id', 'tr_code', 'amount'
                ]));
                $entry->delete();
            }
        });

        return redirect()->route('general.journal.index')
            ->with('success', 'All journal entries processed successfully!');
    }
}
