<?php
# ────────────── lee_gwena ──────────────
# Code by: ashley_gwena
# Created: 2026-03-12
# Notes: Cashbook configuration and GL linkage
# ───────────────────────────────────────

namespace App\Http\Controllers\Accounting;

use App\Http\Controllers\Controller;
use App\Http\Requests\ChartOfAccounts\CashbookRequest;
use App\Models\Cashbook;
use App\Models\Currency;
use App\Models\GeneralLedgerParentAccount;
use App\Models\TrustAccount;

class CashbookController extends Controller
{
    public function index()
    {
        $cashbooks = Cashbook::query()->with(['currency', 'glAccount'])->orderBy('name')->get();

        return view('modules.edit.cashbooks.index', compact('cashbooks'));
    }

    public function create()
    {
        $currencies = Currency::query()->orderBy('currency_code')->get();
        $glAccounts = GeneralLedgerParentAccount::query()->orderBy('account_code')->get();

        return view('modules.edit.cashbooks.create', compact('currencies', 'glAccounts'));
    }

    public function store(CashbookRequest $request)
    {
        $payload = $this->mapPayload($request);

        $this->enforceCashbookRules($payload);

        $payload['created_by'] = auth()->id();
        $payload['updated_by'] = auth()->id();

        Cashbook::query()->create($payload);

        return redirect()->route('cashbooks.index')->with('success', 'Cashbook created.');
    }

    public function show(Cashbook $cashbook)
    {
        return view('modules.edit.cashbooks.show', compact('cashbook'));
    }

    public function edit(Cashbook $cashbook)
    {
        $currencies = Currency::query()->orderBy('currency_code')->get();
        $glAccounts = GeneralLedgerParentAccount::query()->orderBy('account_code')->get();

        return view('modules.edit.cashbooks.edit', compact('cashbook', 'currencies', 'glAccounts'));
    }

    public function update(CashbookRequest $request, Cashbook $cashbook)
    {
        $payload = $this->mapPayload($request);

        $this->enforceCashbookRules($payload);

        $payload['updated_by'] = auth()->id();
        $cashbook->update($payload);

        return redirect()->route('cashbooks.index')->with('success', 'Cashbook updated.');
    }

    public function destroy(Cashbook $cashbook)
    {
        $hasEntries = \App\Models\CashbookEntry::query()
            ->where('cashbook_id', $cashbook->id)
            ->exists();

        if ($hasEntries) {
            return back()->withErrors(['cashbook' => 'Cashbooks with entries cannot be deleted.']);
        }

        $cashbook->delete();

        return redirect()->route('cashbooks.index')->with('success', 'Cashbook deleted.');
    }

    private function mapPayload(CashbookRequest $request): array
    {
        $isTrust = (bool) $request->input('is_trust', false);

        return [
            'name' => $request->input('name'),
            'account_number' => $request->input('account_number'),
            'currency' => $request->input('currency'),
            'gl_account_id' => $request->input('default_gl_account_id'),
            'is_trust' => $isTrust,
        ];
    }

    private function enforceCashbookRules(array $payload): void
    {
        $glAccount = GeneralLedgerParentAccount::query()->with('accountType')->find($payload['gl_account_id']);
        if (!$glAccount || !$glAccount->accountType) {
            return;
        }

        $typeName = strtolower(trim((string) ($glAccount->accountType->name ?? '')));
        $typeCode = strtolower(trim((string) ($glAccount->accountType->code ?? '')));
        $typeBucket = trim($typeName . ' ' . $typeCode);

        $blocked = ['liability', 'equity', 'revenue', 'income', 'expense'];
        foreach ($blocked as $word) {
            if ($typeBucket !== '' && str_contains($typeBucket, $word)) {
                abort(422, 'Cashbooks must map to an asset GL account.');
            }
        }
    }
}
