package pl.polskalokalnie.lead;

import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Table;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.annotations.ColumnDefault;

/**
 * Kontakt marketingowy (lead) - jedno zrodlo prawdy dla odbiorcow kampanii. Zasilany z trzech
 * zrodel: zarejestrowani uzytkownicy (synchronizacja), reczne dodanie/import oraz formularze.
 * Zgody ({@code emailConsent}/{@code smsConsent}) i trwale rezygnacje ({@code emailOptOut}/
 * {@code smsOptOut}) decyduja o kwalifikacji leada do wysylki na danym kanale.
 */
@Entity
@Table(name = "leads", indexes = {
        @Index(name = "idx_leads_email", columnList = "email"),
        @Index(name = "idx_leads_phone", columnList = "phone"),
        @Index(name = "idx_leads_user_id", columnList = "userId")
})
public class Lead {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 160)
    private String name;

    @Column(length = 180)
    private String email;

    @Column(length = 30)
    private String phone;

    @Column(length = 120)
    private String city;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 20)
    private LeadSource source = LeadSource.MANUAL;

    // Powiazanie z kontem uzytkownika, gdy source = REGISTERED_USER.
    private Long userId;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 20)
    @ColumnDefault("'NEW'")
    private LeadStatus status = LeadStatus.NEW;

    // EAGER: tagi sa male i zawsze potrzebne w filtrach segmentow oraz odpowiedziach DTO
    // (mapowanie odbywa sie poza sesja, bo open-in-view=false).
    @ElementCollection(fetch = jakarta.persistence.FetchType.EAGER)
    @CollectionTable(name = "lead_tags", joinColumns = @JoinColumn(name = "lead_id"))
    @Column(name = "tag", length = 60)
    private List<String> tags = new ArrayList<>();

    @Column(nullable = false)
    @ColumnDefault("true")
    private boolean emailConsent = true;

    @Column(nullable = false)
    @ColumnDefault("true")
    private boolean smsConsent = true;

    // Trwala rezygnacja - raz ustawiona nie jest cofana przez kampanie ani synchronizacje.
    @Column(nullable = false)
    @ColumnDefault("false")
    private boolean emailOptOut = false;

    @Column(nullable = false)
    @ColumnDefault("false")
    private boolean smsOptOut = false;

    @Column(length = 2000)
    private String notes;

    @Column(nullable = false, updatable = false)
    private Instant createdAt;

    @PrePersist
    void onCreate() {
        if (createdAt == null) {
            createdAt = Instant.now();
        }
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public LeadSource getSource() {
        return source;
    }

    public void setSource(LeadSource source) {
        this.source = source;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public LeadStatus getStatus() {
        return status;
    }

    public void setStatus(LeadStatus status) {
        this.status = status;
    }

    public List<String> getTags() {
        return tags;
    }

    public void setTags(List<String> tags) {
        this.tags = tags;
    }

    public boolean isEmailConsent() {
        return emailConsent;
    }

    public void setEmailConsent(boolean emailConsent) {
        this.emailConsent = emailConsent;
    }

    public boolean isSmsConsent() {
        return smsConsent;
    }

    public void setSmsConsent(boolean smsConsent) {
        this.smsConsent = smsConsent;
    }

    public boolean isEmailOptOut() {
        return emailOptOut;
    }

    public void setEmailOptOut(boolean emailOptOut) {
        this.emailOptOut = emailOptOut;
    }

    public boolean isSmsOptOut() {
        return smsOptOut;
    }

    public void setSmsOptOut(boolean smsOptOut) {
        this.smsOptOut = smsOptOut;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public Instant getCreatedAt() {
        return createdAt;
    }
}
