package com.imprimelibros.erp.presupuesto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import com.imprimelibros.erp.presupuesto.validation.ConsistentTiradas;
import com.imprimelibros.erp.presupuesto.validation.Par;
import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups;
import com.imprimelibros.erp.presupuesto.validation.Tamanio;

import com.imprimelibros.erp.common.HtmlStripConverter;

import jakarta.persistence.*;

@ConsistentTiradas(groups = PresupuestoValidationGroups.DatosGenerales.class)
@Tamanio(groups = PresupuestoValidationGroups.DatosGenerales.class)
@Entity
@Table(name = "presupuesto")
public class Presupuesto implements Cloneable{

    public enum TipoEncuadernacion {
        fresado("presupuesto.fresado"),
        cosido("presupuesto.cosido"),
        grapado("presupuesto.grapado"),
        espiral("presupuesto.espiral"),
        wireo("presupuesto.wireo");

        private final String messageKey;

        TipoEncuadernacion(String messageKey) {
            this.messageKey = messageKey;
        }

        public String getMessageKey() {
            return messageKey;
        }
    }

    public enum TipoImpresion {
        negro("presupuesto.blanco-negro"),
        negrohq("presupuesto.blanco-negro-premium"),
        color("presupuesto.color"),
        colorhq("presupuesto.color-premium");

        private final String messageKey;

        TipoImpresion(String messageKey) {
            this.messageKey = messageKey;
        }

        public String getMessageKey() {
            return messageKey;
        }
    }

    public enum TipoCubierta {
        tapaBlanda("presupuesto.tapa-blanda"),
        tapaDura("presupuesto.tapa-dura"),
        tapaDuraLomoRedondo("presupuesto.tapa-dura-lomo-redondo");

        private final String messageKey;

        TipoCubierta(String messageKey) {
            this.messageKey = messageKey;
        }

        public String getMessageKey() {
            return messageKey;
        }
    }

    @Override
    public Presupuesto clone() {
        try {
            return (Presupuesto) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

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

    @NotNull(message = "{presupuesto.errores.tipo-encuadernacion}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @Enumerated(EnumType.STRING)
    @Column(name = "tipo_encuadernacion")
    private TipoEncuadernacion tipoEncuadernacion = TipoEncuadernacion.fresado;

    @Convert(converter = HtmlStripConverter.class)
    @NotBlank(message = "{presupuesto.errores.titulo}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @Column(name = "titulo")
    private String titulo;

    @Convert(converter = HtmlStripConverter.class)
    @Column(name = "autor")
    private String autor;

    @Convert(converter = HtmlStripConverter.class)
    @Column(name = "isbn")
    private String isbn;

    @NotNull(message = "{presupuesto.errores.tirada1}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @Column(name = "tirada1")
    private Integer tirada1;

    @Column(name = "tirada2")
    private Integer tirada2;

    @Column(name = "tirada3")
    private Integer tirada3;

    @Column(name = "tirada4")
    private Integer tirada4;

    @Column(name = "selected_tirada")
    private Integer selectedTirada;

    @NotNull(message = "{presupuesto.errores.ancho}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @Column(name = "ancho")
    private Integer ancho;

    @NotNull(message = "{presupuesto.errores.alto}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @Column(name = "alto")
    private Integer alto;

    @Column(name = "formatoPersonalizado")
    private Boolean formatoPersonalizado;

    @Par(message = "{presupuesto.errores.paginasNegro.par}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @NotNull(message = "{presupuesto.errores.paginasNegro.required}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @Column(name = "paginas_negro")
    private Integer paginasNegro;

    @Par(message = "{presupuesto.errores.paginasColor.par}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @NotNull(message = "{presupuesto.errores.paginasColor.required}", groups = PresupuestoValidationGroups.DatosGenerales.class)
    @Column(name = "paginas_color")
    private Integer paginasColor;

    @Column(name = "posicion_paginas_color")
    private String posicionPaginasColor;

    @Column(name = "paginas_color_total")
    private Integer paginasColorTotal;

    @NotNull(message = "{presupuesto.errores.tipo-impresion}", groups = PresupuestoValidationGroups.Interior.class)
    @Enumerated(EnumType.STRING)
    @Column(name = "tipo_impresion")
    private TipoImpresion tipoImpresion = TipoImpresion.negro;

    @NotNull(message = "{presupuesto.errores.papel-interior}", groups = PresupuestoValidationGroups.Interior.class)
    @Column(name = "papel_interior_id")
    private Integer papelInteriorId;

    @NotNull(message = "{presupuesto.errores.gramaje-interior}", groups = PresupuestoValidationGroups.Interior.class)
    @Column(name = "gramaje_interior")
    private Integer gramajeInterior;

    @NotNull(message = "{presupuesto.errores.tipo-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
    @Enumerated(EnumType.STRING)
    @Column(name = "tipo_cubierta")
    private TipoCubierta tipoCubierta = TipoCubierta.tapaBlanda;

    @Column(name = "solapas_cubierta")
    private Boolean solapasCubierta = false;

    @Column(name = "tamanio_solapas_cubierta")
    private Integer tamanioSolapasCubierta;

    @Column(name = "cubierta_caras")
    private Integer cubiertaCaras;

    @Column(name = "papel_guardas_id")
    private Integer papelGuardasId;

    @Column(name = "gramaje_guardas")
    private Integer gramajeGuardas;

    @Column(name = "guardas_impresas")
    private Integer guardasImpresas;

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

    @NotNull(message = "{presupuesto.errores.papel-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
    @Column(name = "papel_cubierta_id")
    private Integer papelCubiertaId = 2;

    @NotNull(message = "{presupuesto.errores.gramaje-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
    @Column(name = "gramaje_cubierta")
    private Integer gramajeCubierta = 240;

    @NotNull(message = "{presupuesto.errores.acabado-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
    @Column(name = "acabado")
    private Integer acabado = 1; 

    @Column(name = "sobrecubierta")
    private Boolean sobrecubierta = false;
    @Column(name = "papel_sobrecubierta_id")
    private Integer papelSobrecubiertaId = 2;
    @Column(name = "gramaje_sobrecubierta")
    private Integer gramajeSobrecubierta = 170;
    @Column(name = "tamanio_solapas_sobrecubierta")
    private Integer tamanioSolapasSobrecubierta = 80;
    @Column(name = "acabado_sobrecubierta")
    private Integer acabadoSobrecubierta = 0; // 0: sin acabado,

    @Column(name = "faja")
    private Boolean faja = false;
    @Column(name = "papel_faja_id")
    private Integer papelFajaId = 2;
    @Column(name = "gramaje_faja")
    private Integer gramajeFaja = 170;
    @Column(name = "tamanio_solapas_faja")
    private Integer tamanioSolapasFaja = 80;
    @Column(name = "acabado_faja")
    private Integer acabadoFaja = 0; // 0: sin acabado
    @Column(name = "alto_faja")
    private Integer altoFaja = 0;

    @Column(name = "presupuesto_maquetacion")
    private Boolean presupuestoMaquetacion = false;
    @Column(name = "presupuesto_maquetacion_data")
    private String presupuestoMaquetacionData;


    // Getters y Setters 
    public String getAutor() {
        return autor;
    }

    public void setAutor(String autor) {
        this.autor = autor;
    }

    public String getIsbn() {
        return isbn;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public Integer getTirada1() {
        return tirada1;
    }

    public void setTirada1(Integer tirada1) {
        this.tirada1 = tirada1;
    }

    public Integer getTirada2() {
        return tirada2;
    }

    public void setTirada2(Integer tirada2) {
        this.tirada2 = tirada2;
    }

    public Integer getTirada3() {
        return tirada3;
    }

    public void setTirada3(Integer tirada3) {
        this.tirada3 = tirada3;
    }

    public Integer getTirada4() {
        return tirada4;
    }

    public Integer[] getTiradas() {
        return new Integer[] { tirada1, tirada2, tirada3, tirada4 };
    }

    public void setTirada4(Integer tirada4) {
        this.tirada4 = tirada4;
    }

    public Integer getAncho() {
        return ancho;
    }

    public void setAncho(Integer ancho) {
        this.ancho = ancho;
    }

    public Integer getAlto() {
        return alto;
    }

    public void setAlto(Integer alto) {
        this.alto = alto;
    }

    public Boolean getFormatoPersonalizado() {
        return formatoPersonalizado;
    }

    public void setFormatoPersonalizado(Boolean formatoPersonalizado) {
        this.formatoPersonalizado = formatoPersonalizado;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public Long getId() {
        return id;
    }

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

    public Integer getPaginasNegro() {
        return paginasNegro;
    }

    public void setPaginasNegro(Integer paginasNegro) {
        this.paginasNegro = paginasNegro;
    }

    public Integer getPaginasColor() {
        return paginasColor;
    }

    public void setPaginasColor(Integer paginasColor) {
        this.paginasColor = paginasColor;
    }

    public TipoEncuadernacion getTipoEncuadernacion() {
        return tipoEncuadernacion;
    }

    public void setTipoEncuadernacion(TipoEncuadernacion tipoEncuadernacion) {
        this.tipoEncuadernacion = tipoEncuadernacion;
    }

    public String getPosicionPaginasColor() {
        return posicionPaginasColor;
    }

    public void setPosicionPaginasColor(String posicionPaginasColor) {
        this.posicionPaginasColor = posicionPaginasColor;
    }

    public Integer getPaginasColorTotal() {
        return paginasColorTotal;
    }

    public void setPaginasColorTotal(Integer paginasColorTotal) {
        this.paginasColorTotal = paginasColorTotal;
    }

    public TipoImpresion getTipoImpresion() {
        return tipoImpresion;
    }

    public void setTipoImpresion(TipoImpresion tipoImpresion) {
        this.tipoImpresion = tipoImpresion;
    }

    public Integer getPapelInteriorId() {
        return papelInteriorId;
    }

    public void setPapelInteriorId(Integer papelInteriorId) {
        this.papelInteriorId = papelInteriorId;
    }

    public Integer getGramajeInterior() {
        return gramajeInterior;
    }

    public void setGramajeInterior(Integer gramajeInterior) {
        this.gramajeInterior = gramajeInterior;
    }

    public TipoCubierta getTipoCubierta() {
        return tipoCubierta;
    }

    public void setTipoCubierta(TipoCubierta tipoCubierta) {
        this.tipoCubierta = tipoCubierta;
    }

    public Boolean getSolapasCubierta() {
        return solapasCubierta;
    }

    public void setSolapasCubierta(Boolean solapasCubierta) {
        this.solapasCubierta = solapasCubierta;
    }

    public Integer getTamanioSolapasCubierta() {
        return tamanioSolapasCubierta;
    }

    public void setTamanioSolapasCubierta(Integer tamanioSolapasCubierta) {
        this.tamanioSolapasCubierta = tamanioSolapasCubierta;
    }

    public Integer getCubiertaCaras() {
        return cubiertaCaras;
    }

    public void setCubiertaCaras(Integer cubiertaCaras) {
        this.cubiertaCaras = cubiertaCaras;
    }

    public Integer getPapelGuardasId() {
        return papelGuardasId;
    }

    public void setPapelGuardasId(Integer papelGuardasId) {
        this.papelGuardasId = papelGuardasId;
    }

    public Integer getGramajeGuardas() {
        return gramajeGuardas;
    }

    public void setGramajeGuardas(Integer gramajeGuardas) {
        this.gramajeGuardas = gramajeGuardas;
    }

    public Integer getGuardasImpresas() {
        return guardasImpresas;
    }

    public void setGuardasImpresas(Integer guardasImpresas) {
        this.guardasImpresas = guardasImpresas;
    }

    public String getCabezada() {
        return cabezada;
    }

    public void setCabezada(String cabezada) {
        this.cabezada = cabezada;
    }

    public Integer getPapelCubiertaId() {
        return papelCubiertaId;
    }

    public void setPapelCubiertaId(Integer papelCubiertaId) {
        this.papelCubiertaId = papelCubiertaId;
    }

    public Integer getGramajeCubierta() {
        return gramajeCubierta;
    }

    public void setGramajeCubierta(Integer gramajeCubierta) {
        this.gramajeCubierta = gramajeCubierta;
    }

    public Integer getAcabado() {
        return acabado;
    }

    public void setAcabado(Integer acabado) {
        this.acabado = acabado;
    }

    public Boolean getSobrecubierta() {
        return sobrecubierta;
    }

    public void setSobrecubierta(Boolean sobrecubierta) {
        this.sobrecubierta = sobrecubierta;
    }

    public Integer getPapelSobrecubiertaId() {
        return papelSobrecubiertaId;
    }

    public void setPapelSobrecubiertaId(Integer papelSobrecubiertaId) {
        this.papelSobrecubiertaId = papelSobrecubiertaId;
    }

    public Integer getGramajeSobrecubierta() {
        return gramajeSobrecubierta;
    }

    public void setGramajeSobrecubierta(Integer gramajeSobrecubierta) {
        this.gramajeSobrecubierta = gramajeSobrecubierta;
    }

    public Integer getTamanioSolapasSobrecubierta() {
        return tamanioSolapasSobrecubierta;
    }

    public void setTamanioSolapasSobrecubierta(Integer tamanioSolapasSobrecubierta) {
        this.tamanioSolapasSobrecubierta = tamanioSolapasSobrecubierta;
    }

    public Integer getAcabadoSobrecubierta() {
        return acabadoSobrecubierta;
    }

    public void setAcabadoSobrecubierta(Integer acabadoSobrecubierta) {
        this.acabadoSobrecubierta = acabadoSobrecubierta;
    }

    public Boolean getFaja() {
        return faja;
    }

    public void setFaja(Boolean faja) {
        this.faja = faja;
    }

    public Integer getPapelFajaId() {
        return papelFajaId;
    }

    public void setPapelFajaId(Integer papelFajaId) {
        this.papelFajaId = papelFajaId;
    }

    public Integer getGramajeFaja() {
        return gramajeFaja;
    }

    public void setGramajeFaja(Integer gramajeFaja) {
        this.gramajeFaja = gramajeFaja;
    }

    public Integer getTamanioSolapasFaja() {
        return tamanioSolapasFaja;
    }

    public void setTamanioSolapasFaja(Integer tamanioSolapasFaja) {
        this.tamanioSolapasFaja = tamanioSolapasFaja;
    }

    public Integer getAcabadoFaja() {
        return acabadoFaja;
    }

    public void setAcabadoFaja(Integer acabadoFaja) {
        this.acabadoFaja = acabadoFaja;
    }

    public Integer getAltoFaja() {
        return altoFaja;
    }

    public void setAltoFaja(Integer altoFaja) {
        this.altoFaja = altoFaja;
    }

    public Integer getSelectedTirada() {
        return selectedTirada;
    }

    public void setSelectedTirada(Integer selectedTirada) {
        this.selectedTirada = selectedTirada;
    }

    public Boolean getPresupuestoMaquetacion() {
        return presupuestoMaquetacion;
    }
    public void setPresupuestoMaquetacion(Boolean presupuestoMaquetacion) {
        this.presupuestoMaquetacion = presupuestoMaquetacion;
    }
    public String getPresupuestoMaquetacionData() {
        return presupuestoMaquetacionData;
    }
    public void setPresupuestoMaquetacionData(String presupuestoMaquetacionData) {
        this.presupuestoMaquetacionData = presupuestoMaquetacionData;
    }

    public String resumenPresupuesto() {
        return String.format("%s - %s - %dx%d mm - %d Páginas (N:%d C:%d) - Tira:%d",
                this.titulo,
                this.tipoEncuadernacion,
                this.ancho,
                this.alto,
                this.paginasNegro + this.paginasColorTotal,
                this.paginasNegro,
                this.paginasColorTotal,
                this.selectedTirada != null ? this.selectedTirada : 0);
    }
}
