using CashLineERP.Contracts.Finance;

namespace CashLineERP.Application.Finance;

public sealed class ForeignExchangeRevaluationService : IForeignExchangeRevaluationService
{
    private readonly IForeignExchangeRevaluationRepository _repository;

    public ForeignExchangeRevaluationService(IForeignExchangeRevaluationRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<ForeignExchangeRevaluationResponse> GetForeignExchangeRevaluations() =>
        _repository.GetForeignExchangeRevaluations().Select(Map).ToArray();

    public ForeignExchangeRevaluationResponse? GetForeignExchangeRevaluation(long foreignExchangeRevaluationId)
    {
        var revaluation = _repository.GetForeignExchangeRevaluation(foreignExchangeRevaluationId);
        return revaluation is null ? null : Map(revaluation);
    }

    public ForeignExchangeRevaluationResponse CreateForeignExchangeRevaluation(CreateForeignExchangeRevaluationRequest request) =>
        Map(_repository.Create(new CreateForeignExchangeRevaluationCommand(
            request.AccountingPeriodId,
            request.RevaluationDate,
            request.IncludeAccountsReceivable,
            request.IncludeAccountsPayable,
            request.IncludeCashAccounts,
            request.Notes)));

    public ForeignExchangeRevaluationResponse SubmitForeignExchangeRevaluation(long foreignExchangeRevaluationId, long actorUserId) =>
        Map(_repository.Submit(foreignExchangeRevaluationId, actorUserId));

    public ForeignExchangeRevaluationResponse ApproveForeignExchangeRevaluation(long foreignExchangeRevaluationId, long actorUserId) =>
        Map(_repository.Approve(foreignExchangeRevaluationId, actorUserId));

    public ForeignExchangeRevaluationResponse PostForeignExchangeRevaluation(long foreignExchangeRevaluationId, long actorUserId) =>
        Map(_repository.Post(foreignExchangeRevaluationId, actorUserId));

    private static ForeignExchangeRevaluationResponse Map(ForeignExchangeRevaluationDetailView revaluation) =>
        new(
            revaluation.ForeignExchangeRevaluationId,
            revaluation.RevaluationNumber,
            revaluation.AccountingPeriodId,
            revaluation.RevaluationDate,
            revaluation.BaseCurrencyCode,
            revaluation.Notes,
            revaluation.StatusCode,
            revaluation.TotalGainBaseAmount,
            revaluation.TotalLossBaseAmount,
            revaluation.NetVarianceBaseAmount,
            revaluation.SubmittedAtUtc,
            revaluation.SubmittedByUserId,
            revaluation.ApprovedAtUtc,
            revaluation.ApprovedByUserId,
            revaluation.PostedAtUtc,
            revaluation.PostedByUserId,
            revaluation.GeneralLedgerBatchId,
            revaluation.Lines.Select(line => new ForeignExchangeRevaluationLineResponse(
                line.ForeignExchangeRevaluationLineId,
                line.LineNumber,
                line.SourceTypeCode,
                line.SourceDocumentId,
                line.SourceDocumentNumber,
                line.SourceGeneralLedgerAccountId,
                line.BranchId,
                line.PartyId,
                line.SourceDocumentDate,
                line.CurrencyCode,
                line.ForeignAmount,
                line.CarryingRateToBase,
                line.RevaluationRateToBase,
                line.CarryingBaseAmount,
                line.RevaluedBaseAmount,
                line.VarianceBaseAmount)).ToArray());
}
