using CashLineERP.Contracts.Inventory;

namespace CashLineERP.Application.Inventory;

public sealed class ReplenishmentRuleService : IReplenishmentRuleService
{
    private readonly IReplenishmentRuleRepository _repository;

    public ReplenishmentRuleService(IReplenishmentRuleRepository repository)
    {
        _repository = repository;
    }

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

    public ReplenishmentRuleResponse? GetReplenishmentRule(long replenishmentRuleId)
    {
        var rule = _repository.GetReplenishmentRule(replenishmentRuleId);
        return rule is null ? null : Map(rule);
    }

    public ReplenishmentRuleResponse CreateReplenishmentRule(CreateReplenishmentRuleRequest request) =>
        Map(_repository.Create(new CreateReplenishmentRuleCommand(
            request.RuleName,
            request.BranchId,
            request.TargetWarehouseId,
            request.PreferredSourceWarehouseId,
            request.ItemId,
            request.UnitOfMeasureCode,
            request.ReorderPointQuantity,
            request.TargetSafetyStockQuantity,
            request.TargetStockQuantity,
            request.SourceSafetyStockQuantity,
            request.Priority,
            request.EffectiveFromDate,
            request.EffectiveToDate,
            request.Notes)));

    public ReplenishmentRuleResponse SubmitReplenishmentRule(long replenishmentRuleId, long actorUserId) =>
        Map(_repository.Submit(replenishmentRuleId, actorUserId));

    public ReplenishmentRuleResponse ApproveReplenishmentRule(long replenishmentRuleId, long actorUserId) =>
        Map(_repository.Approve(replenishmentRuleId, actorUserId));

    public ReplenishmentRuleResponse ActivateReplenishmentRule(long replenishmentRuleId, long actorUserId) =>
        Map(_repository.Activate(replenishmentRuleId, actorUserId));

    public ReplenishmentEvaluationResponse EvaluateReplenishment(ReplenishmentEvaluationRequest request) =>
        Map(_repository.Evaluate(new ReplenishmentEvaluationCommand(
            request.BranchId,
            request.AsOfDate,
            request.TargetWarehouseId,
            request.ItemId)));

    public ReorderPlanningResponse BuildReorderPlan(ReorderPlanningRequest request) =>
        Map(_repository.BuildReorderPlan(new ReorderPlanningCommand(
            request.BranchId,
            request.AsOfDate,
            request.TargetWarehouseId,
            request.ItemId)));

    public ReorderPlanHandoffResponse CreateOperationalHandoff(long actorUserId, ReorderPlanningRequest request) =>
        Map(_repository.CreateOperationalHandoff(new ReorderPlanningCommand(
            request.BranchId,
            request.AsOfDate,
            request.TargetWarehouseId,
            request.ItemId), actorUserId));

    private static ReplenishmentRuleResponse Map(ReplenishmentRuleDetailView rule) =>
        new(
            rule.ReplenishmentRuleId,
            rule.RuleCode,
            rule.RuleName,
            rule.BranchId,
            rule.TargetWarehouseId,
            rule.PreferredSourceWarehouseId,
            rule.ItemId,
            rule.UnitOfMeasureCode,
            rule.ReorderPointQuantity,
            rule.TargetSafetyStockQuantity,
            rule.TargetStockQuantity,
            rule.SourceSafetyStockQuantity,
            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 ReplenishmentEvaluationResponse Map(ReplenishmentEvaluationView evaluation) =>
        new(
            evaluation.BranchId,
            evaluation.AsOfDate,
            evaluation.Lines.Select(line => new ReplenishmentEvaluationLineResponse(
                line.ReplenishmentRuleId,
                line.RuleCode,
                line.RuleName,
                line.BranchId,
                line.TargetWarehouseId,
                line.SourceWarehouseId,
                line.ItemId,
                line.UnitOfMeasureCode,
                line.ReorderPointQuantity,
                line.TargetSafetyStockQuantity,
                line.TargetStockQuantity,
                line.TargetOnHandQuantity,
                line.TargetShortfallQuantity,
                line.SourceOnHandQuantity,
                line.SourceAvailableToTransferQuantity,
                line.RecommendedTransferQuantity,
                line.RecommendationStatusCode,
                line.Notes)).ToArray());

    private static ReorderPlanningResponse Map(ReorderPlanningView planning) =>
        new(
            planning.BranchId,
            planning.AsOfDate,
            planning.Lines.Select(line => new ReorderPlanningLineResponse(
                line.ReplenishmentRuleId,
                line.RuleCode,
                line.RuleName,
                line.BranchId,
                line.TargetWarehouseId,
                line.SourceWarehouseId,
                line.ItemId,
                line.UnitOfMeasureCode,
                line.ReorderPointQuantity,
                line.TargetSafetyStockQuantity,
                line.TargetStockQuantity,
                line.TargetOnHandQuantity,
                line.IsBelowReorderPoint,
                line.IsBelowSafetyStock,
                line.RecommendedReorderQuantity,
                line.RecommendedTransferQuantity,
                line.RecommendedProcurementQuantity,
                line.PlanningActionCode,
                line.Notes)).ToArray());

    private static ReorderPlanHandoffResponse Map(ReorderPlanHandoffView handoff) =>
        new(
            handoff.BranchId,
            handoff.AsOfDate,
            handoff.TransferDrafts.Select(draft => new ReorderPlanHandoffTransferDraftResponse(
                draft.WarehouseTransferId,
                draft.TransferNumber,
                draft.BranchId,
                draft.FromWarehouseId,
                draft.ToWarehouseId,
                draft.LineCount,
                draft.TotalTransferQuantity,
                draft.SourceReplenishmentRuleIds)).ToArray(),
            handoff.ProcurementDrafts.Select(draft => new ReorderPlanHandoffProcurementDraftResponse(
                draft.PurchaseRequisitionId,
                draft.RequisitionNumber,
                draft.BranchId,
                draft.RequesterUserId,
                draft.LineCount,
                draft.EstimatedTotalAmount,
                draft.SourceReplenishmentRuleIds)).ToArray());
}
