<?php

namespace App\Services;

use App\Models\ChartOfAccount;
use App\Models\Account;
use Illuminate\Support\Collection;

class ChartOfAccountService
{
    /**
     * Get the top 5 parent chart of accounts with their complete hierarchy
     * including children and linked accounts
     *
     * @return Collection
     */
    public function getHierarchyWithAccounts(): Collection
    {
        // Get top 5 parent accounts (where parent_id is null)
        $topParents = ChartOfAccount::whereNull('parent_id')
            ->limit(5)
            ->get();

        return $topParents->map(function ($parent) {
            return $this->buildHierarchyNode($parent);
        });
    }

    /**
     * Recursively build a hierarchy node with children and accounts
     *
     * @param ChartOfAccount $chartOfAccount
     * @return array
     */
    private function buildHierarchyNode(ChartOfAccount $chartOfAccount): array
    {
        // Get direct children of this chart of account
        $children = ChartOfAccount::where('parent_id', $chartOfAccount->id)->get();

        // Get linked accounts for this chart of account
        $accounts = Account::where('chart_of_account_id', $chartOfAccount->id)->get();

        // Build the node structure
        $node = [
            'id' => $chartOfAccount->id,
            'name' => $chartOfAccount->name,
            'accounts' => $accounts->map(function ($account) {
                return [
                    'id' => $account->id,
                    'name' => $account->name,
                ];
            })->toArray(),
            'children' => []
        ];

        // Recursively build children
        foreach ($children as $child) {
            $node['children'][] = $this->buildHierarchyNode($child);
        }

        return $node;
    }

    /**
     * Get a specific chart of account with its complete hierarchy
     *
     * @param int $chartOfAccountId
     * @return array|null
     */
    public function getChartOfAccountHierarchy(int $chartOfAccountId): ?array
    {
        $chartOfAccount = ChartOfAccount::find($chartOfAccountId);

        if (!$chartOfAccount) {
            return null;
        }

        return $this->buildHierarchyNode($chartOfAccount);
    }

    /**
     * Get all chart of accounts in a flat structure with their accounts
     *
     * @return Collection
     */
    public function getAllWithAccounts(): Collection
    {
        return ChartOfAccount::with(['accounts' => function ($query) {
            $query->select('id', 'name', 'chart_of_account_id');
        }])->get()->map(function ($chartOfAccount) {
            return [
                'id' => $chartOfAccount->id,
                'name' => $chartOfAccount->name,
                'parent_id' => $chartOfAccount->parent_id,
                'accounts' => $chartOfAccount->accounts->map(function ($account) {
                    return [
                        'id' => $account->id,
                        'name' => $account->name,
                    ];
                })->toArray(),
            ];
        });
    }
}
