package ru.yandex.qe.dispenser.domain.d;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import ru.yandex.qe.dispenser.domain.resources_model.ExternalResource;
import ru.yandex.qe.dispenser.domain.resources_model.QuotaRequestDelivery;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@JsonIgnoreProperties(ignoreUnknown = true)
public final class DeliveryRequestDto {

    private final String deliveryId;
    private final String authorUid;
    private final List<DeliverableRequestDto> deliverables;

    @JsonCreator
    public DeliveryRequestDto(@JsonProperty("deliveryId") String deliveryId,
                              @JsonProperty("authorUid") String authorUid,
                              @JsonProperty("deliverables") List<DeliverableRequestDto> deliverables) {
        this.deliveryId = deliveryId;
        this.authorUid = authorUid;
        this.deliverables = deliverables;
    }

    public static Builder builder() {
        return new Builder();
    }

    public String getDeliveryId() {
        return deliveryId;
    }

    public String getAuthorUid() {
        return authorUid;
    }

    public List<DeliverableRequestDto> getDeliverables() {
        return deliverables;
    }

    public static DeliveryRequestDto from(QuotaRequestDelivery delivery) {
        final Builder builder = builder()
                .deliveryId(delivery.getId().toString())
                .authorUid(Long.toString(delivery.getAuthorUid()));

        for (ExternalResource externalResource : delivery.getExternalResources()) {
            final DeliverableRequestDto deliverableRequestDto = DeliverableRequestDto.builder()
                    .serviceId(delivery.getAbcServiceId())
                    .resourceId(externalResource.getResourceId().toString())
                    .delta(DeliverableDeltaDto.builder()
                            .amount(externalResource.getAmount())
                            .unitKey(externalResource.getUnitKey())
                            .build())
                    .meta(DeliverableMetaRequestDto.builder()
                            .bigOrderId(externalResource.getBigOrderId())
                            .campaignId(delivery.getCampaignId())
                            .quotaRequestId(delivery.getQuotaRequestId())
                            .build())
                    .build();
            builder.addDeliverable(deliverableRequestDto);
        }

        return builder.build();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        DeliveryRequestDto that = (DeliveryRequestDto) o;
        return Objects.equals(deliveryId, that.deliveryId) &&
                Objects.equals(authorUid, that.authorUid) &&
                Objects.equals(deliverables, that.deliverables);
    }

    @Override
    public int hashCode() {
        return Objects.hash(deliveryId, authorUid, deliverables);
    }

    @Override
    public String toString() {
        return "DeliveryRequestDto{" +
                "deliveryId='" + deliveryId + '\'' +
                ", authorUid='" + authorUid + '\'' +
                ", deliverables=" + deliverables +
                '}';
    }

    public static final class Builder {

        private final List<DeliverableRequestDto> deliverables = new ArrayList<>();

        private String deliveryId;
        private String authorUid;

        private Builder() {
        }

        public Builder deliveryId(String deliveryId) {
            this.deliveryId = deliveryId;
            return this;
        }

        public Builder authorUid(String authorUid) {
            this.authorUid = authorUid;
            return this;
        }

        public Builder addDeliverable(DeliverableRequestDto deliverable) {
            this.deliverables.add(deliverable);
            return this;
        }

        public DeliveryRequestDto build() {
            Objects.requireNonNull(deliveryId, "Delivery id is required");
            Objects.requireNonNull(authorUid, "Author uid is required");
            return new DeliveryRequestDto(deliveryId, authorUid, deliverables);
        }

    }

}
