package com.example.items.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import javax.print.Doc;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;

@Entity
@NoArgsConstructor
@AllArgsConstructor

@Table(name="employees")
public class Employee implements UserDetails {

    //ENUMS
    public enum UserRole {
        EMPLOYEE,
        MANAGER;
    }

    public enum EmployeePosition {
        SALES_MANAGER,
        SALES_REP,
        ADVERTISING_MANAGER,
        SOFTWARE_DEVELOPER;
    }

    public enum EmployeeDepartment {
        SALES,
        MARKETING,
        IT,
        HR,
        ACCOUNTING;
    }

    @Id
    @Column(name = "user_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name="first_name")
    @Size(min=2, max=40,message = "First Name must be between 2 and 40 characters")
    private String firstName;

    @Column(name="last_name")
    @Size(min=2, max=40,message = "Last Name must be between 2 and 40 characters")
    private String lastName;

    @Column(name="email", unique = true)
    @NotNull
    @Pattern(regexp = "^[A-Za-z0-9+_.-]+@(.+)$",message = "Invalid email format")
    private String email;

    @Column(name="passcode")
    @NotNull
    private String passcode;

    @Transient
    private String passcodeConfirm;

    @Column(name="phone")
    @Pattern(regexp = "^$|[1-9]\\d{2}-\\d{3}-\\d{4}",message="Please enter phone number in the following format: Ex. 555-555-5555")
    private String phone;

    @Column(name="hire_date")
    @CreationTimestamp
    private LocalDate hireDate;

    @Enumerated
    @Column(name="position")
    @NotNull
    private EmployeePosition position;

    @Enumerated
    @Column(name="department")
    @NotNull
    private EmployeeDepartment department;

    @Column(name="birthDate")
    @DateTimeFormat(pattern = "yyyy/MM/dd")
    private String birthDate;

    @Column(name="salary")
    @NotNull
    private Double salary;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="locationId")
    private Location location;

    @Column(name="emergencyContactPhone")
    @Pattern(regexp = "^$|[1-9]\\d{2}-\\d{3}-\\d{4}",message="Please enter phone number in the following format: Ex. 555-555-5555")
    private String emergencyContactPhone;

    @Column(name="emergencyContactName")
    private String emergencyContactName;

    @Enumerated
    @Column(name="role")
    private UserRole role;


    @OneToMany(mappedBy = "employee", cascade = CascadeType.REMOVE, orphanRemoval = true)
    private Set<Document>document;

    @OneToMany(mappedBy = "employee", cascade = CascadeType.REMOVE, orphanRemoval = true)
    private Set<Request>request;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

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

    public String getPasscode() {
        return passcode;
    }

    public void setPasscode(String passcode) {
        this.passcode = passcode;
    }

    public String getPasscodeConfirm() {
        return passcodeConfirm;
    }

    public void setPasscodeConfirm(String passcodeConfirm) {
        this.passcodeConfirm = passcodeConfirm;
    }

    public String getPhone() {
        return phone;
    }

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

    public LocalDate getHireDate() {
        return hireDate;
    }

    public void setHireDate(LocalDate hireDate) {
        this.hireDate = hireDate;
    }

    public EmployeePosition getPosition() {
        return position;
    }

    public void setPosition(EmployeePosition position) {
        this.position = position;
    }

    public EmployeeDepartment getDepartment() {
        return department;
    }

    public void setDepartment(EmployeeDepartment department) {
        this.department = department;
    }

    public String getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(String birthDate) {
        this.birthDate = birthDate;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    public String getEmergencyContactPhone() {
        return emergencyContactPhone;
    }

    public void setEmergencyContactPhone(String emergencyContactPhone) {
        this.emergencyContactPhone = emergencyContactPhone;
    }

    public String getEmergencyContactName() {
        return emergencyContactName;
    }

    public void setEmergencyContactName(String emergencyContactName) {
        this.emergencyContactName = emergencyContactName;
    }

    public UserRole getRole() {
        return role;
    }

    public void setRole(UserRole role) {
        this.role = role;
    }

    public Set<Document> getDocument() {
        return document;
    }

    public void setDocument(Set<Document> document) {
        this.document = document;
    }

    public Set<Request> getRequest() {
        return request;
    }

    public void setRequest(Set<Request> request) {
        this.request = request;
    }

    public Set<GrantedAuthority> getAuthorities() {
        Set<GrantedAuthority> authorities =new HashSet<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_" + role.name()));
        return authorities;
    }

    @Override
    public String getPassword() {
        return passcode;
    }

    @Override
    public String getUsername() {
        return email;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}
