using CashLineERP.Contracts.MasterData;

namespace CashLineERP.Application.MasterData;

public sealed class ReferenceDataGovernanceService : IReferenceDataGovernanceService
{
    private readonly IReferenceDataGovernanceRepository _repository;

    public ReferenceDataGovernanceService(IReferenceDataGovernanceRepository repository)
    {
        _repository = repository;
    }

    public MasterDataGovernanceOverviewResponse GetOverview()
    {
        var overview = _repository.GetOverview();
        return new MasterDataGovernanceOverviewResponse(
            overview.TotalEntries,
            overview.ActiveEntries,
            overview.SubmittedEntries,
            overview.CurrencyEntries,
            overview.UnitOfMeasureEntries,
            overview.TaxCodeEntries,
            overview.WarehouseEntries);
    }

    public IReadOnlyCollection<ReferenceDataEntryResponse> GetEntries(string? referenceTypeCode = null, bool activeOnly = false) =>
        _repository.GetEntries(referenceTypeCode, activeOnly).Select(Map).ToArray();

    public ReferenceDataEntryResponse? GetEntry(long referenceDataEntryId)
    {
        var entry = _repository.GetEntry(referenceDataEntryId);
        return entry is null ? null : Map(entry);
    }

    public ReferenceDataEntryResponse CreateReferenceDataEntry(CreateReferenceDataEntryRequest request) =>
        Map(_repository.Create(new CreateReferenceDataEntryCommand(
            request.ReferenceTypeCode,
            request.ReferenceCode,
            request.ReferenceName,
            request.LocalizedName,
            request.DescriptionText,
            request.AttributesJson,
            request.EffectiveFrom,
            request.EffectiveTo)));

    public ReferenceDataEntryResponse SubmitReferenceDataEntry(long referenceDataEntryId, long actorUserId) =>
        Map(_repository.Submit(referenceDataEntryId, actorUserId));

    public ReferenceDataEntryResponse ApproveReferenceDataEntry(long referenceDataEntryId, long actorUserId) =>
        Map(_repository.Approve(referenceDataEntryId, actorUserId));

    public ReferenceDataEntryResponse ActivateReferenceDataEntry(long referenceDataEntryId, long actorUserId) =>
        Map(_repository.Activate(referenceDataEntryId, actorUserId));

    private static ReferenceDataEntryResponse Map(ReferenceDataEntryDetailView entry) =>
        new(
            entry.ReferenceDataEntryId,
            entry.EntryCode,
            entry.ReferenceTypeCode,
            entry.ReferenceCode,
            entry.ReferenceName,
            entry.LocalizedName,
            entry.DescriptionText,
            entry.AttributesJson,
            entry.StatusCode,
            entry.IsActive,
            entry.EffectiveFrom,
            entry.EffectiveTo,
            entry.SubmittedAtUtc,
            entry.SubmittedByUserId,
            entry.ApprovedAtUtc,
            entry.ApprovedByUserId,
            entry.ActivatedAtUtc,
            entry.ActivatedByUserId);
}
