<?php
# ────────────── lee_gwena ──────────────
# Code by: ashley_gwena
# Created: 2026-03-31
# Notes: Subaccount management scoped to a parent GL account
# ───────────────────────────────────────

namespace App\Http\Controllers\Accounting;

use App\Http\Controllers\Controller;
use App\Http\Requests\ChartOfAccounts\StoreGLSubaccountRequest;
use App\Http\Requests\ChartOfAccounts\UpdateGLSubaccountRequest;
use App\Models\GeneralLedgerParentAccount;
use App\Models\GeneralLedgerSubaccount;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class SubaccountController extends Controller
{
    public function index(Request $request, GeneralLedgerParentAccount $parent)
    {
        $query = GeneralLedgerSubaccount::query()
            ->with(['parent'])
            ->where('parent_id', $parent->id);

        if ($search = $request->string('search')->trim()->value()) {
            $query->where(function ($inner) use ($search) {
                $inner->where('sub_code', 'like', "%{$search}%")
                    ->orWhere('account_name', 'like', "%{$search}%");
            });
        }

        $accounts = $query->orderBy('sub_code')->get();

        return view('chart_of_accounts.subaccounts.index', compact('parent', 'accounts'));
    }

    public function create(GeneralLedgerParentAccount $parent)
    {
        return view('chart_of_accounts.subaccounts.create', compact('parent'));
    }

    public function store(StoreGLSubaccountRequest $request, GeneralLedgerParentAccount $parent)
    {
        $data = $this->mapAccountPayload($request, $parent->id);
        $data['created_by'] = auth()->id();
        $data['updated_by'] = auth()->id();

        GeneralLedgerSubaccount::query()->create($data);

        return redirect()->route('subaccounts.index', $parent)->with('success', 'Subaccount created.');
    }

    public function show(GeneralLedgerParentAccount $parent, GeneralLedgerSubaccount $subaccount)
    {
        $this->ensureParent($parent, $subaccount);
        $metrics = $this->accountMetrics($subaccount->id);
        $createdByName = $subaccount->created_by
            ? User::query()->where('id', $subaccount->created_by)->value('name')
            : null;
        $updatedByName = $subaccount->updated_by
            ? User::query()->where('id', $subaccount->updated_by)->value('name')
            : null;

        return view('chart_of_accounts.subaccounts.show', [
            'parent' => $parent,
            'account' => $subaccount->load('parent'),
            'metrics' => $metrics,
            'createdByName' => $createdByName,
            'updatedByName' => $updatedByName,
        ]);
    }

    public function edit(GeneralLedgerParentAccount $parent, GeneralLedgerSubaccount $subaccount)
    {
        $this->ensureParent($parent, $subaccount);

        return view('chart_of_accounts.subaccounts.edit', compact('parent', 'subaccount'));
    }

    public function update(UpdateGLSubaccountRequest $request, GeneralLedgerParentAccount $parent, GeneralLedgerSubaccount $subaccount)
    {
        $this->ensureParent($parent, $subaccount);

        if ($this->hasTransactions($subaccount->id)) {
            return back()->withErrors(['account' => 'Accounts with transactions cannot be edited.']);
        }

        $data = $this->mapAccountPayload($request, $parent->id);
        $data['updated_by'] = auth()->id();
        $subaccount->update($data);

        return redirect()->route('subaccounts.index', $parent)->with('success', 'Subaccount updated.');
    }

    public function destroy(GeneralLedgerParentAccount $parent, GeneralLedgerSubaccount $subaccount)
    {
        $this->ensureParent($parent, $subaccount);

        if ($this->hasTransactions($subaccount->id)) {
            return back()->withErrors(['account' => 'Accounts with transactions cannot be deleted.']);
        }

        $subaccount->delete();

        return redirect()->route('subaccounts.index', $parent)->with('success', 'Subaccount deleted.');
    }

    private function ensureParent(GeneralLedgerParentAccount $parent, GeneralLedgerSubaccount $subaccount): void
    {
        if ((int) $subaccount->parent_id !== (int) $parent->id) {
            abort(404);
        }
    }

    private function mapAccountPayload(Request $request, int $parentId): array
    {
        return [
            'sub_code' => $request->input('sub_code'),
            'account_name' => $request->input('account_name'),
            'parent_id' => $parentId,
            'is_active' => (bool) $request->input('is_active', true),
        ];
    }

    private function hasTransactions(int $accountId): bool
    {
        return DB::table('journal_lines')->where('gl_account_id', $accountId)->exists();
    }

    private function accountMetrics(int $accountId): array
    {
        $transactionCount = DB::table('journal_lines')->where('gl_account_id', $accountId)->count();
        $lastTransactionDate = DB::table('journal_lines')->where('gl_account_id', $accountId)->max('created_at');
        $balance = DB::table('journal_lines')
            ->where('gl_account_id', $accountId)
            ->selectRaw('COALESCE(SUM(debit - credit), 0) as balance')
            ->value('balance');

        return [
            'current_balance' => $balance ?? 0,
            'transaction_count' => $transactionCount,
            'last_transaction_date' => $lastTransactionDate,
        ];
    }
}
