package com.social.media.domain.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Entity
@Table(name = "users", schema = "core_business",
       uniqueConstraints = {
           @UniqueConstraint(name = "chk_users_company_email_unique", 
                           columnNames = {"company_id", "email"}),
           @UniqueConstraint(name = "users_user_code_key", 
                           columnNames = {"user_code"})
       })
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    
    @Column(name = "user_code", nullable = false, length = 20)
    private String userCode;
    
    @NotNull(message = "Company ID é obrigatório")
    @Column(name = "company_id", nullable = false)
    private Long companyId;
    
    @Column(name = "parent_user_id")
    private Long parentUserId;
    
    @NotBlank(message = "Nome é obrigatório")
    @Size(max = 255, message = "Nome deve ter no máximo 255 caracteres")
    @Column(name = "name", nullable = false, length = 255)
    private String name;
    
    @NotBlank(message = "Email é obrigatório")
    @Email(message = "Email deve ser válido")
    @Size(max = 320, message = "Email deve ter no máximo 320 caracteres")
    @Column(name = "email", nullable = false, length = 320)
    private String email;
    
    @Pattern(regexp = "^[0-9]{11}$|^$", message = "CPF deve ter 11 dígitos")
    @Size(max = 11, message = "CPF deve ter no máximo 11 caracteres")
    @Column(name = "cpf", length = 11)
    private String cpf;
    
    @Size(max = 20, message = "Telefone deve ter no máximo 20 caracteres")
    @Column(name = "phone", length = 20)
    private String phone;
    
    @Size(max = 1000, message = "Avatar URL deve ter no máximo 1000 caracteres")
    @Column(name = "avatar_url", length = 1000)
    private String avatarUrl;
    
    @Size(max = 100, message = "Posição deve ter no máximo 100 caracteres")
    @Column(name = "position", length = 100)
    private String position;
    
    @Size(max = 100, message = "Departamento deve ter no máximo 100 caracteres")
    @Column(name = "department", length = 100)
    private String department;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "type", nullable = false)
    private UserType type = UserType.USER;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false)
    private UserStatus status = UserStatus.PENDING_VERIFICATION;
    
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "configuration", nullable = false, columnDefinition = "jsonb")
    private Map<String, Object> configuration;
    
    @Column(name = "whatsapp_enabled", nullable = false)
    private Boolean whatsappEnabled = false;
    
    @Column(name = "profile_verified", nullable = false)
    private Boolean profileVerified = false;
    
    @Column(name = "manager_id")
    private Long managerId;
    
    @Min(value = 0, message = "Nível organizacional deve ser no mínimo 0")
    @Max(value = 10, message = "Nível organizacional deve ser no máximo 10")
    @Column(name = "organizational_level")
    private Integer organizationalLevel = 0;
    
    @Pattern(regexp = "^[A-Za-z_/]+$", message = "Timezone deve ter formato válido")
    @Size(max = 50, message = "Timezone deve ter no máximo 50 caracteres")
    @Column(name = "timezone", length = 50)
    private String timezone = "America/Sao_Paulo";
    
    @Pattern(regexp = "^[a-z]{2}(-[A-Z]{2})?$", message = "Language deve ter formato válido (ex: pt-BR)")
    @Size(max = 10, message = "Language deve ter no máximo 10 caracteres")
    @Column(name = "language", length = 10)
    private String language = "pt-BR";
    
    @Column(name = "registration_date", nullable = false)
    private LocalDateTime registrationDate;
    
    @Column(name = "last_access_date")
    private LocalDateTime lastAccessDate;
    
    @Column(name = "deleted", nullable = false)
    private Boolean deleted = false;
    
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;
    
    // Enums
    public enum UserType {
        USER, ADMIN, MANAGER
    }
    
    public enum UserStatus {
        PENDING_VERIFICATION, ACTIVE, INACTIVE, SUSPENDED, BLOCKED
    }
    
    // Construtores
    public User() {
    }
    
    public User(String name, String email, Long companyId) {
        this.name = name;
        this.email = email;
        this.companyId = companyId;
        this.registrationDate = LocalDateTime.now();
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    public User(String name, String email, String phone, Long companyId) {
        this.name = name;
        this.email = email;
        this.phone = phone;
        this.companyId = companyId;
        this.registrationDate = LocalDateTime.now();
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    // Lifecycle callbacks
    @PrePersist
    protected void onCreate() {
        LocalDateTime now = LocalDateTime.now();
        if (createdAt == null) {
            createdAt = now;
        }
        if (registrationDate == null) {
            registrationDate = now;
        }
        updatedAt = now;
        if (deleted == null) {
            deleted = false;
        }
        if (whatsappEnabled == null) {
            whatsappEnabled = false;
        }
        if (profileVerified == null) {
            profileVerified = false;
        }
        if (configuration == null) {
            configuration = new HashMap<>();
        }
        if (type == null) {
            type = UserType.USER;
        }
        if (status == null) {
            status = UserStatus.PENDING_VERIFICATION;
        }
        if (organizationalLevel == null) {
            organizationalLevel = 0;
        }
        if (timezone == null) {
            timezone = "America/Sao_Paulo";
        }
        if (language == null) {
            language = "pt-BR";
        }
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
    
    // Getters e Setters
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getUserCode() {
        return userCode;
    }
    
    public void setUserCode(String userCode) {
        this.userCode = userCode;
    }
    
    public Long getCompanyId() {
        return companyId;
    }
    
    public void setCompanyId(Long companyId) {
        this.companyId = companyId;
    }
    
    public Long getParentUserId() {
        return parentUserId;
    }
    
    public void setParentUserId(Long parentUserId) {
        this.parentUserId = parentUserId;
    }
    
    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 getCpf() {
        return cpf;
    }
    
    public void setCpf(String cpf) {
        this.cpf = cpf;
    }
    
    public String getPhone() {
        return phone;
    }
    
    public void setPhone(String phone) {
        this.phone = phone;
    }
    
    public String getAvatarUrl() {
        return avatarUrl;
    }
    
    public void setAvatarUrl(String avatarUrl) {
        this.avatarUrl = avatarUrl;
    }
    
    public String getPosition() {
        return position;
    }
    
    public void setPosition(String position) {
        this.position = position;
    }
    
    public String getDepartment() {
        return department;
    }
    
    public void setDepartment(String department) {
        this.department = department;
    }
    
    public UserType getType() {
        return type;
    }
    
    public void setType(UserType type) {
        this.type = type;
    }
    
    public UserStatus getStatus() {
        return status;
    }
    
    public void setStatus(UserStatus status) {
        this.status = status;
    }
    
    public Map<String, Object> getConfiguration() {
        return configuration;
    }
    
    public void setConfiguration(Map<String, Object> configuration) {
        this.configuration = configuration;
    }
    
    public Boolean getWhatsappEnabled() {
        return whatsappEnabled;
    }
    
    public void setWhatsappEnabled(Boolean whatsappEnabled) {
        this.whatsappEnabled = whatsappEnabled;
    }
    
    public Boolean getProfileVerified() {
        return profileVerified;
    }
    
    public void setProfileVerified(Boolean profileVerified) {
        this.profileVerified = profileVerified;
    }
    
    public Long getManagerId() {
        return managerId;
    }
    
    public void setManagerId(Long managerId) {
        this.managerId = managerId;
    }
    
    public Integer getOrganizationalLevel() {
        return organizationalLevel;
    }
    
    public void setOrganizationalLevel(Integer organizationalLevel) {
        this.organizationalLevel = organizationalLevel;
    }
    
    public String getTimezone() {
        return timezone;
    }
    
    public void setTimezone(String timezone) {
        this.timezone = timezone;
    }
    
    public String getLanguage() {
        return language;
    }
    
    public void setLanguage(String language) {
        this.language = language;
    }
    
    public LocalDateTime getRegistrationDate() {
        return registrationDate;
    }
    
    public void setRegistrationDate(LocalDateTime registrationDate) {
        this.registrationDate = registrationDate;
    }
    
    public LocalDateTime getLastAccessDate() {
        return lastAccessDate;
    }
    
    public void setLastAccessDate(LocalDateTime lastAccessDate) {
        this.lastAccessDate = lastAccessDate;
    }
    
    public Boolean getDeleted() {
        return deleted;
    }
    
    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }
    
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
    
    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }
    
    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }
    
    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }
    
    // equals e hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) && Objects.equals(email, user.email);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id, email);
    }
    
    // toString
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userCode='" + userCode + '\'' +
                ", companyId=" + companyId +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", type=" + type +
                ", status=" + status +
                ", deleted=" + deleted +
                ", createdAt=" + createdAt +
                '}';
    }
}
