package com.sn.sowsysrestapi.domain.entity;

import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import javax.persistence.*;
import java.time.OffsetDateTime;
import java.util.Random;

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Table(name = "user")
public class User {

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

    @Column(name = "user_code", unique = true, updatable = false)
    private String userCode;

    @Column(name = "activation_code", updatable = false)
    private String activationCode;

    @Column(name = "admin_role")
    private Boolean admin;

    @Column(name = "is_activeted")
    private Boolean isActiveted = false;

    @Column(name = "first_name", length = 20)
    private String firstName;

    @Column(name = "last_name", length = 20)
    private String lastName;

    @Column(name = "email", length = 40, updatable = true, unique = true)
    private String email;

    @Column(name = "username", length = 20, updatable = false, unique = true)
    private String username;

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

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

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

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

    @CreationTimestamp
    @Column(name = "created_on")
    private OffsetDateTime createdOn;

    @UpdateTimestamp
    @Column(name = "updated_on")
    private OffsetDateTime updatedOn;

    @OneToOne//(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "report_directory_id", foreignKey = @ForeignKey(name = "FK_REPORT_DIRECTORY_ID_USER"))
    private ReportDirectory reportDirectory;

    public boolean passwordMatchWith(String password) {

        return getPassword().equals(password);
    }

    public boolean passwordDoesNotMatchWith(String password) {

        return !passwordMatchWith(password);
    }

    public void activateAccount() {

        this.isActiveted = true;
    }

    @PrePersist
    private void userCodeGenerator() {

        String generatedUserCode = codeGenerator(8);
        setUserCode(generatedUserCode);

        String generatedActivationCode = codeGenerator(5);
        setActivationCode(generatedActivationCode.toUpperCase());

    }

    private String codeGenerator(int codeLength) {

        // 55 char string. There is no o, O, l, i, I, 0, and 1 to avoid confusion.
        String charString = "ABCDEFGHJKLMNPQRSTUVWXYZ" +
                "abcdefghjkmnpqrstuvwxyz" +
                "23456789";

        Random random = new Random();

        StringBuilder code = new StringBuilder();

        for (int i = 0; i < codeLength; i++) {
            code.append(charString.charAt(random.nextInt(charString.length())));
        }

        // Get the generated code and store it in a String that will be returned
        String generatedCode = String.valueOf(code);

        return generatedCode;
    }

    public boolean isAdmin() {
        return this.admin;
    }
}
