package br.com.elotech.base.model;

import br.com.elotech.base.crypto.Crypto;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import lombok.ToString;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

@EqualsAndHashCode
@ToString
public class RegistroModel {

    private Long id;

    private String modulo;
    private String nome;
    private LocalDate validade;
    private LocalDate dataLiberacao;
    private String situacao;
    private Long entidade;
    private Long qtdEntidades;
    private String codigo;
    private String senha;
    private String hash;

    private boolean hashFormatOld;

    public static String getCalculatedHash(LocalDate validade, String modulo, String nome, String codigo) {

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/uuuu");

        StringBuilder builder = new StringBuilder();
        builder.append(validade.format(formatter))
                .append(modulo)
                .append(nome)
                .append(codigo);

        return builder.toString();
    }

    public static String getCalculatedHashOld(LocalDate validade, LocalDate dataLiberacao, String modulo, String nome,
            String codigo, String senha) {

        StringBuilder builder = new StringBuilder();

        builder.append(senha)
                .append(validade.format(DateTimeFormatter.ISO_DATE))
                .append(dataLiberacao.format(DateTimeFormatter.ISO_DATE))
                .append(nome).append(modulo);

        return builder.toString();

    }

    public boolean isValid(String hash) {

        if (hash == null) {
            return false;
        }

        return Crypto.setHash(getCalculatedHash()).equals(hash);
    }

    public String getHash() {

        return Crypto.setHash(getInternalCalculatedHash());
    }


    private String getInternalCalculatedHashOld() {
        return RegistroModel.getCalculatedHashOld(validade, dataLiberacao, modulo, nome, codigo, senha);
    }

    private String getInternalCalculatedHash() {
        return RegistroModel.getCalculatedHash(validade, modulo, nome, codigo);
    }

    public static RegistroModel newInstance() {
        return new RegistroModel();
    }

    public String getCalculatedHash() {

        if (hashFormatOld) {
            return getInternalCalculatedHashOld();
        }
        return getInternalCalculatedHash();

    }

    public String getModulo() {
        return modulo;
    }

    public String getNome() {
        return nome;
    }

    public LocalDate getValidade() {
        return validade;
    }

    public LocalDate getDataLiberacao() {
        return dataLiberacao;
    }

    public String getCodigo() {
        return codigo;
    }

    public String getSenha() {
        return senha;
    }


    public void setModulo(String modulo) {
        this.modulo = modulo;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public void setValidade(LocalDate validade) {
        this.validade = validade;
    }

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public long getQtdDiasRestantes(){
        return ChronoUnit.DAYS.between(
                Instant.now(),
                getValidade().atStartOfDay().toInstant(ZoneOffset.UTC))+2;
    }

}
 
