using CashLineERP.Contracts.Finance;

namespace CashLineERP.Application.Finance;

public sealed class FinanceCloseJournalService : IFinanceCloseJournalService
{
    private readonly IFinanceCloseJournalRepository _repository;

    public FinanceCloseJournalService(IFinanceCloseJournalRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<FinanceCloseJournalResponse> GetCloseJournals() =>
        _repository.GetCloseJournals().Select(Map).ToArray();

    public FinanceCloseJournalResponse? GetCloseJournal(long financeCloseJournalId)
    {
        var journal = _repository.GetCloseJournal(financeCloseJournalId);
        return journal is null ? null : Map(journal);
    }

    public FinanceCloseJournalResponse CreateCloseJournal(CreateFinanceCloseJournalRequest request)
    {
        var journal = _repository.Create(new CreateFinanceCloseJournalCommand(
            request.AccountingPeriodId,
            request.BranchId,
            request.JournalClassCode,
            request.PostingDate,
            request.DocumentDate,
            request.Notes,
            request.Lines.Select(line => new CreateFinanceCloseJournalLineCommand(
                line.GeneralLedgerAccountId,
                line.BranchId,
                line.DepartmentId,
                line.PartyId,
                line.ItemId,
                line.DebitAmount,
                line.CreditAmount,
                line.CurrencyCode,
                line.FxRate,
                line.LineDescription)).ToArray()));

        return Map(journal);
    }

    public FinanceCloseJournalResponse SubmitCloseJournal(long financeCloseJournalId, long actorUserId) =>
        Map(_repository.Submit(financeCloseJournalId, actorUserId));

    public FinanceCloseJournalResponse ApproveCloseJournal(long financeCloseJournalId, long actorUserId) =>
        Map(_repository.Approve(financeCloseJournalId, actorUserId));

    public FinanceCloseJournalResponse PostCloseJournal(long financeCloseJournalId, long actorUserId) =>
        Map(_repository.Post(financeCloseJournalId, actorUserId));

    private static FinanceCloseJournalResponse Map(FinanceCloseJournalDetailView journal) =>
        new(
            journal.FinanceCloseJournalId,
            journal.CloseJournalNumber,
            journal.AccountingPeriodId,
            journal.BranchId,
            journal.JournalClassCode,
            journal.PostingDate,
            journal.DocumentDate,
            journal.Notes,
            journal.StatusCode,
            journal.TotalDebitAmount,
            journal.TotalCreditAmount,
            journal.SubmittedAtUtc,
            journal.SubmittedByUserId,
            journal.ApprovedAtUtc,
            journal.ApprovedByUserId,
            journal.PostedAtUtc,
            journal.PostedByUserId,
            journal.GeneralLedgerBatchId,
            journal.Lines.Select(line => new FinanceCloseJournalLineResponse(
                line.FinanceCloseJournalLineId,
                line.LineNumber,
                line.GeneralLedgerAccountId,
                line.BranchId,
                line.DepartmentId,
                line.PartyId,
                line.ItemId,
                line.DebitAmount,
                line.CreditAmount,
                line.CurrencyCode,
                line.FxRate,
                line.LineDescription)).ToArray());
}
