<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Models;

use App\Core\Model;
use App\Core\App;

class Account extends Model
{
    protected static string $table = 'chart_of_accounts';
    protected static array $fillable = [
        'account_code', 'name_ar', 'name_en', 'account_type', 'account_nature',
        'parent_id', 'level', 'is_header', 'is_active', 'is_system',
        'description_ar', 'description_en', 'opening_balance', 'current_balance',
        'currency', 'cost_center_id', 'is_bank_account', 'bank_account_id',
    ];
    protected static bool $timestamps = true;
    protected static bool $softDelete = true;

    public static function findByCode(string $code): ?static
    {
        $row = static::query()->where('account_code', '=', $code)->where('is_archived', '=', 0)->first();
        if ($row === null) {
            return null;
        }
        $instance = new static($row);
        $instance->exists = true;
        return $instance;
    }

    public static function getByType(string $type): array
    {
        return static::query()
            ->where('account_type', '=', $type)
            ->where('is_active', '=', 1)
            ->where('is_archived', '=', 0)
            ->orderBy('account_code', 'ASC')
            ->get();
    }

    public static function getPostableAccounts(): array
    {
        return static::query()
            ->where('is_header', '=', 0)
            ->where('is_active', '=', 1)
            ->where('is_archived', '=', 0)
            ->orderBy('account_code', 'ASC')
            ->get();
    }

    public function children(): array
    {
        return static::query()
            ->where('parent_id', '=', $this->id)
            ->where('is_archived', '=', 0)
            ->orderBy('account_code', 'ASC')
            ->get();
    }

    public function parent(): ?array
    {
        if ($this->parent_id === null) {
            return null;
        }
        return static::query()->where('id', '=', $this->parent_id)->first();
    }

    public static function getTree(): array
    {
        $all = static::query()
            ->where('is_archived', '=', 0)
            ->orderBy('account_code', 'ASC')
            ->get();

        return self::buildTree($all, null);
    }

    private static function buildTree(array $accounts, ?int $parentId): array
    {
        $tree = [];
        foreach ($accounts as $account) {
            $pid = $account['parent_id'] !== null ? (int) $account['parent_id'] : null;
            if ($pid === $parentId) {
                $account['children'] = self::buildTree($accounts, (int) $account['id']);
                $tree[] = $account;
            }
        }
        return $tree;
    }

    public static function search(string $term): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT * FROM chart_of_accounts
             WHERE is_archived = 0
               AND (account_code LIKE ? OR name_ar LIKE ? OR name_en LIKE ?)
             ORDER BY account_code ASC
             LIMIT 50",
            ["%{$term}%", "%{$term}%", "%{$term}%"]
        );
    }
}
