<?php

namespace Modules\Accounts\Repositories;

use Illuminate\Support\Collection;
use Modules\Accounts\Models\AccountTransaction;
use Modules\Accounts\Models\ChartOfAccount;

class TransactionRepository
{
    public function latestBalanceForAccount(int $accountId): float
    {
        return (float) (AccountTransaction::query()
            ->where('account_id', $accountId)
            ->orderByDesc('transaction_date')
            ->orderByDesc('id')
            ->value('balance') ?? 0);
    }

    public function createMany(array $transactions): void
    {
        foreach ($transactions as $transaction) {
            AccountTransaction::query()->create($transaction);
        }
    }

    public function deleteByVoucher(int $voucherId): void
    {
        AccountTransaction::query()->where('voucher_id', $voucherId)->delete();
    }

    public function trialBalance(?string $fromDate = null, ?string $toDate = null): Collection
    {
        return ChartOfAccount::query()
            ->ledger()
            ->withSum(['transactions as total_debit' => function ($query) use ($fromDate, $toDate) {
                $query->when($fromDate, fn ($inner) => $inner->whereDate('transaction_date', '>=', $fromDate))
                    ->when($toDate, fn ($inner) => $inner->whereDate('transaction_date', '<=', $toDate));
            }], 'debit')
            ->withSum(['transactions as total_credit' => function ($query) use ($fromDate, $toDate) {
                $query->when($fromDate, fn ($inner) => $inner->whereDate('transaction_date', '>=', $fromDate))
                    ->when($toDate, fn ($inner) => $inner->whereDate('transaction_date', '<=', $toDate));
            }], 'credit')
            ->orderBy('account_code')
            ->get();
    }

    public function generalLedger(array $filters = []): Collection
    {
        return AccountTransaction::query()
            ->with(['account', 'voucher'])
            ->when($filters['account_id'] ?? null, fn ($query, $accountId) => $query->where('account_id', $accountId))
            ->when($filters['from_date'] ?? null, fn ($query, $fromDate) => $query->whereDate('transaction_date', '>=', $fromDate))
            ->when($filters['to_date'] ?? null, fn ($query, $toDate) => $query->whereDate('transaction_date', '<=', $toDate))
            ->orderBy('transaction_date')
            ->orderBy('id')
            ->get();
    }

    public function accountStatement(int $accountId, ?string $fromDate = null, ?string $toDate = null): Collection
    {
        return AccountTransaction::query()
            ->with(['voucher'])
            ->where('account_id', $accountId)
            ->when($fromDate, fn ($query) => $query->whereDate('transaction_date', '>=', $fromDate))
            ->when($toDate, fn ($query) => $query->whereDate('transaction_date', '<=', $toDate))
            ->orderBy('transaction_date')
            ->orderBy('id')
            ->get();
    }
}
