using CashLineERP.Contracts.Procurement;

namespace CashLineERP.Application.Procurement;

public sealed class RfqEvaluationService : IRfqEvaluationService
{
    private readonly IRfqEvaluationRepository _repository;

    public RfqEvaluationService(IRfqEvaluationRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<RfqEvaluationResponse> GetEvaluations(long? rfqId = null) =>
        _repository.GetEvaluations(rfqId).Select(MapEvaluation).ToArray();

    public RfqEvaluationResponse? GetEvaluation(long evaluationId)
    {
        var evaluation = _repository.GetEvaluation(evaluationId);
        return evaluation is null ? null : MapEvaluation(evaluation);
    }

    public RfqEvaluationResponse CreateEvaluation(CreateRfqEvaluationRequest request)
    {
        var evaluation = _repository.Create(new CreateRfqEvaluationCommand(
            request.RequestForQuotationId,
            request.EvaluationDate,
            request.Notes,
            request.Lines.Select(line => new CreateRfqEvaluationLineCommand(
                line.QuotationId,
                line.SupplierId,
                line.PriceScore,
                line.CommercialScore,
                line.DeliveryScore,
                line.QualityScore,
                line.RankNumber,
                line.IsRecommended,
                line.Notes)).ToArray()));

        return MapEvaluation(evaluation);
    }

    public RfqEvaluationResponse FinalizeRecommendation(long evaluationId, long actorUserId) =>
        MapEvaluation(_repository.FinalizeRecommendation(evaluationId, actorUserId));

    public PurchaseOrderResponse AwardPurchaseOrder(long evaluationId, AwardPurchaseOrderRequest request) =>
        MapPurchaseOrder(_repository.AwardPurchaseOrder(
            evaluationId,
            request.ActorUserId,
            request.PurchaseOrderDate,
            request.DefaultWarehouseId));

    private static RfqEvaluationResponse MapEvaluation(RfqEvaluationDetailView evaluation) =>
        new(
            evaluation.RfqEvaluationId,
            evaluation.RequestForQuotationId,
            evaluation.EvaluationNumber,
            evaluation.EvaluationDate,
            evaluation.StatusCode,
            evaluation.RecommendedSupplierId,
            evaluation.ApprovedQuotationId,
            evaluation.Notes,
            evaluation.Lines.Select(line => new RfqEvaluationLineResponse(
                line.RfqEvaluationLineId,
                line.QuotationId,
                line.SupplierId,
                line.PriceScore,
                line.CommercialScore,
                line.DeliveryScore,
                line.QualityScore,
                line.TotalScore,
                line.RankNumber,
                line.IsRecommended,
                line.Notes)).ToArray());

    private static PurchaseOrderResponse MapPurchaseOrder(PurchaseOrderDetailView purchaseOrder) =>
        new(
            purchaseOrder.PurchaseOrderId,
            purchaseOrder.PurchaseOrderNumber,
            purchaseOrder.BranchId,
            purchaseOrder.SupplierId,
            purchaseOrder.PurchaseRequisitionId,
            purchaseOrder.PurchaseOrderDate,
            purchaseOrder.CurrencyCode,
            purchaseOrder.ExchangeRate,
            purchaseOrder.StatusCode,
            purchaseOrder.SubtotalAmount,
            purchaseOrder.TaxAmount,
            purchaseOrder.TotalAmount,
            purchaseOrder.Lines.Select(line => new PurchaseOrderLineResponse(
                line.PurchaseOrderLineId,
                line.LineNumber,
                line.ItemId,
                line.WarehouseId,
                line.OrderedQuantity,
                line.ReceivedQuantity,
                line.UnitOfMeasureCode,
                line.UnitPrice,
                line.TaxCode,
                line.LineNetAmount,
                line.LineTaxAmount,
                line.LineTotalAmount)).ToArray());
}
