using CashLineERP.Contracts.Pricing;

namespace CashLineERP.Application.Pricing;

public sealed class PricingRuleService : IPricingRuleService
{
    private readonly IPricingRuleRepository _repository;

    public PricingRuleService(IPricingRuleRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<PricingRuleResponse> GetPricingRules(bool activeOnly = false) =>
        _repository.GetPricingRules(activeOnly).Select(Map).ToArray();

    public PricingRuleResponse? GetPricingRule(long pricingRuleId)
    {
        var rule = _repository.GetPricingRule(pricingRuleId);
        return rule is null ? null : Map(rule);
    }

    public PricingRuleResponse CreatePricingRule(CreatePricingRuleRequest request) =>
        Map(_repository.Create(new CreatePricingRuleCommand(
            request.RuleName,
            request.BranchId,
            request.CustomerId,
            request.ItemId,
            request.CurrencyCode,
            request.UnitOfMeasureCode,
            request.MinimumQuantity,
            request.MaximumQuantity,
            request.FixedUnitPrice,
            request.Priority,
            request.EffectiveFromDate,
            request.EffectiveToDate,
            request.Notes)));

    public PricingRuleResponse SubmitPricingRule(long pricingRuleId, long actorUserId) =>
        Map(_repository.Submit(pricingRuleId, actorUserId));

    public PricingRuleResponse ApprovePricingRule(long pricingRuleId, long actorUserId) =>
        Map(_repository.Approve(pricingRuleId, actorUserId));

    public PricingRuleResponse ActivatePricingRule(long pricingRuleId, long actorUserId) =>
        Map(_repository.Activate(pricingRuleId, actorUserId));

    public PricingEvaluationResponse EvaluatePricing(PricingEvaluationRequest request) =>
        Map(_repository.Evaluate(new PricingEvaluationCommand(
            request.BranchId,
            request.CustomerId,
            request.PricingDate,
            request.CurrencyCode,
            request.Lines.Select(line => new PricingEvaluationLineCommand(
                line.ItemId,
                line.OrderedQuantity,
                line.UnitOfMeasureCode,
                line.RequestedUnitPrice)).ToArray())));

    private static PricingRuleResponse Map(PricingRuleDetailView rule) =>
        new(
            rule.PricingRuleId,
            rule.RuleCode,
            rule.RuleName,
            rule.BranchId,
            rule.CustomerId,
            rule.ItemId,
            rule.CurrencyCode,
            rule.UnitOfMeasureCode,
            rule.MinimumQuantity,
            rule.MaximumQuantity,
            rule.FixedUnitPrice,
            rule.Priority,
            rule.EffectiveFromDate,
            rule.EffectiveToDate,
            rule.StatusCode,
            rule.IsActive,
            rule.Notes,
            rule.SubmittedAtUtc,
            rule.SubmittedByUserId,
            rule.ApprovedAtUtc,
            rule.ApprovedByUserId,
            rule.ActivatedAtUtc,
            rule.ActivatedByUserId);

    private static PricingEvaluationResponse Map(PricingEvaluationView evaluation) =>
        new(
            evaluation.BranchId,
            evaluation.CustomerId,
            evaluation.PricingDate,
            evaluation.CurrencyCode,
            evaluation.Lines.Select(line => new PricingEvaluationLineResponse(
                line.ItemId,
                line.OrderedQuantity,
                line.UnitOfMeasureCode,
                line.AppliedUnitPrice,
                line.PricingSourceCode,
                line.PricingRuleId,
                line.PricingRuleCode,
                line.RuleName,
                line.Priority,
                line.Notes)).ToArray());
}
