<?php

namespace App\Support;

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

class CoaParentPickerBuilder
{
    /**
     * @return array<int, array<string, mixed>>
     */
    public static function build(int $companyId, ?string $typeFilter = null): array
    {
        $accounts = Account::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->where('is_active', true)
            ->whereNull('deleted_at')
            ->orderBy('code')
            ->orderBy('name')
            ->get();

        if ($accounts->isEmpty()) {
            return [];
        }

        $accounts->each(function (Account $account) {
            $account->qb_section = QuickBooksChartOfAccounts::sectionForAccount($account);
            $account->qb_account_type = QuickBooksChartOfAccounts::accountTypeLabel($account);
        });

        $sections = QuickBooksChartOfAccounts::sectionsForAccounts($accounts);
        $tree = [];

        foreach ($sections as $section) {
            /** @var Collection<int, Account> $sectionAccs */
            $sectionAccs = $section['accs'] ?? collect();
            if ($sectionAccs->isEmpty()) {
                continue;
            }

            $children = static::buildSectionNodes($sectionAccs, null, $typeFilter);
            if ($children === []) {
                continue;
            }

            $tree[] = [
                'id'         => 'section:' . $section['key'],
                'code'       => '',
                'name'       => $section['label'],
                'type'       => $section['type'] ?? '',
                'type_label' => $section['label'],
                'selectable' => false,
                'is_group'   => true,
                'children'   => $children,
            ];
        }

        return $tree;
    }

    /**
     * @return array<int, array{id: int, parent_id: ?int, code: ?string, name: string, type: string, type_label: string, is_group: bool}>
     */
    public static function accountsMap(int $companyId): array
    {
        return Account::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->where('is_active', true)
            ->whereNull('deleted_at')
            ->orderBy('code')
            ->orderBy('name')
            ->get()
            ->map(fn (Account $account) => [
                'id'         => $account->id,
                'parent_id'  => $account->parent_id,
                'code'       => $account->code,
                'name'       => $account->name,
                'type'       => $account->type,
                'type_label' => QuickBooksChartOfAccounts::accountTypeLabel($account),
                'is_group'   => (bool) $account->is_group,
            ])
            ->values()
            ->all();
    }

    /**
     * @param  Collection<int, Account>  $sectionAccs
     * @return array<int, array<string, mixed>>
     */
    private static function buildSectionNodes(Collection $sectionAccs, ?int $parentId, ?string $typeFilter): array
    {
        $sectionIds = $sectionAccs->pluck('id')->flip();
        $nodes = [];

        $siblings = $sectionAccs->filter(function (Account $account) use ($parentId, $sectionIds) {
            if ($parentId === null) {
                return $account->parent_id === null || !$sectionIds->has($account->parent_id);
            }

            return (int) $account->parent_id === $parentId;
        });

        foreach ($siblings as $account) {
            $children = static::buildSectionNodes($sectionAccs, $account->id, $typeFilter);
            $matchesType = !$typeFilter || $account->type === $typeFilter;

            if (!$matchesType && $children === []) {
                continue;
            }

            $nodes[] = [
                'id'         => $account->id,
                'code'       => $account->code ?? '',
                'name'       => $account->name,
                'type'       => $account->type,
                'type_label' => $account->qb_account_type ?? QuickBooksChartOfAccounts::accountTypeLabel($account),
                'selectable' => $matchesType,
                'is_group'   => (bool) $account->is_group,
                'children'   => $children,
            ];
        }

        return $nodes;
    }
}
