package io.delphiplatform.api.v3.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import io.delphiplatform.api.util.model.ModelUtils;
import io.delphiplatform.api.v3.constant.ApplicationConstants;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.rdb.entity.BasePlaylistLifetimePublicEntity;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
@JsonPropertyOrder(alphabetic = true)
public class PlaylistPublicPositionsDate implements DspPlaylistIdCountryCodeAwareModel {

    @JsonIgnore
    private String dsp;

    @JsonProperty("playlist_id")
    private String playlistId;

    @JsonProperty("playlist")
    private PlaylistSaveFlags playlist;

    @JsonIgnore
    private String countryCode;

    @JsonProperty("dsp_sync_date_time")
    @JsonFormat(shape = Shape.STRING, pattern = ApplicationConstants.ISO_DATE_TIME_PATTERN)
    private List<LocalDateTime> dspSyncDateTime;

    @JsonProperty("playlist_updated_at_date_time")
    @JsonFormat(shape = Shape.STRING, pattern = ApplicationConstants.ISO_DATE_TIME_PATTERN)
    private LocalDateTime playlistUpdatedAtDateTime;

    @JsonProperty("dsp_update_date_time")
    @JsonFormat(shape = Shape.STRING, pattern = ApplicationConstants.ISO_DATE_TIME_PATTERN)
    private LocalDateTime dspUpdateDateTime;

    @JsonProperty("country_code")
    public String getCountryCodeForRepresentation() {
        if (DspConstants.SPOTIFY.equals(this.dsp)) {
            return ModelUtils.publicSpotifyCountryCodeDataToRepresentationState(this.countryCode);
        }

        return countryCode;
    }

    public static PlaylistPublicPositionsDate from(BasePlaylistLifetimePublicEntity entity) {
        if (entity == null) {
            return null;
        }

        return PlaylistPublicPositionsDate.builder()
            .playlistId(entity.getPlaylistId())
            .dsp(entity.getDsp())
            .countryCode(entity.getCountryCode())
            .playlistUpdatedAtDateTime(entity.getPlaylistUpdatedAtDateTime())
            .dspUpdateDateTime(entity.getDspUpdateDateTime())
            .build();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        PlaylistPublicPositionsDate publicPlaylistDate = (PlaylistPublicPositionsDate) o;
        return Objects.equals(this.dsp, publicPlaylistDate.dsp) &&
            Objects.equals(this.playlistId, publicPlaylistDate.playlistId) &&
            Objects.equals(this.playlist, publicPlaylistDate.playlist) &&
            Objects.equals(this.countryCode, publicPlaylistDate.countryCode) &&
            Objects.equals(this.playlistUpdatedAtDateTime, publicPlaylistDate.playlistUpdatedAtDateTime) &&
            Objects.equals(this.dspSyncDateTime, publicPlaylistDate.dspSyncDateTime) &&
            Objects.equals(this.dspUpdateDateTime, publicPlaylistDate.dspUpdateDateTime);
    }

    @Override
    public int hashCode() {
        return Objects.hash(dsp, playlistId, playlist, countryCode, playlistUpdatedAtDateTime, dspSyncDateTime,
            dspUpdateDateTime);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("class PublicPlaylistDate {\n");
        sb.append("    dsp: ").append(toIndentedString(dsp)).append("\n");
        sb.append("    playlistId: ").append(toIndentedString(playlistId)).append("\n");
        sb.append("    playlist: ").append(toIndentedString(playlist)).append("\n");
        sb.append("    countryCode: ").append(toIndentedString(countryCode)).append("\n");
        sb.append("    dspSyncDateTime: ").append(toIndentedString(dspSyncDateTime)).append("\n");
        sb.append("    playlistUpdatedAtDateTime: ").append(toIndentedString(playlistUpdatedAtDateTime)).append("\n");
        sb.append("    dspUpdateDatetime: ").append(toIndentedString(dspUpdateDateTime)).append("\n");
        sb.append("}");
        return sb.toString();
    }

    /**
     * Convert the given object to string with each line indented by 4 spaces (except the first line).
     */
    private String toIndentedString(Object o) {
        if (o == null) {
            return "null";
        }
        return o.toString().replace("\n", "\n    ");
    }
}
