# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
#   * Remove `#managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from datetime import date
from django.utils import timezone
from django.db import models
from django.contrib.auth.models import User
from .validators import validar_fecha
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db.models import Sum
import logging


logger = logging.getLogger(__name__)



class Monedas(models.Model):
    idmoneda = models.AutoField(primary_key=True)
    simbolo = models.CharField(max_length=3, blank=True, null=True)
    nombre = models.CharField(max_length=30, blank=True, null=True)
    bandera = models.CharField(max_length=100, blank=True, null=True)
    codigo = models.CharField(max_length=3,blank=True, null=True)

    class Meta:
        #managed = False
        db_table = 'monedas'


class Empresa(models.Model):
    idempresa = models.AutoField(primary_key=True)
    razonsocial = models.CharField(max_length=100, blank=True, null=True)
    ruc = models.CharField(max_length=11, blank=True, null=True)
    direccion = models.CharField(max_length=150, blank=True, null=True)
    nombrecomercial = models.CharField(max_length=100, blank=True, null=True)
    distrito = models.CharField(max_length=50, blank=True, null=True)
    ciudad = models.CharField(max_length=30, blank=True, null=True)
    telefono = models.CharField(max_length=15, blank=True, null=True)
    fax = models.CharField(max_length=15, blank=True, null=True)
    email = models.CharField(max_length=50, blank=True, null=True)
    logotipo = models.CharField(max_length=150, blank=True, null=True)
    dominio = models.CharField(max_length=100, blank=True, null=True)
    codigofis = models.CharField(max_length=4, blank=True, null=True)
    codigoubigeo = models.CharField(max_length=6, blank=True, null=True)
    resolucion = models.CharField(max_length=100, blank=True, null=True)
    current_sucursal_dir = models.CharField(max_length=300, blank=True, null=True)
    dtr_bconac = models.CharField(max_length=50, blank=True, null=True)
    logo = models.ImageField(upload_to='logos/',blank=True)
    logo2 = models.ImageField(upload_to='logos/',blank=True,null=True) #cambios
    logo3 = models.ImageField(upload_to='logos/',blank=True,null=True) #cambios
    observacion = models.CharField(max_length=200, blank=True, null=True) #cambios
    refran = models.CharField(max_length=100, blank=True, null=True) #cambios
    banco = models.CharField(max_length=100, blank=True, null=True)
    cuenta = models.CharField(max_length=20, blank=True, null=True)
    cci = models.CharField(max_length=30, blank=True, null=True)

    class Meta:
        #managed = False
        db_table = 'empresa'


class Sucursal(models.Model):
    idsucursal = models.AutoField(primary_key=True)
    nombre = models.CharField(max_length=20, blank=True, null=True)
    direccion = models.CharField(max_length=70, blank=True, null=True)
    region = models.CharField(max_length=30, blank=True, null=True)
    telefono = models.CharField(max_length=60, blank=True, null=True)
    fax = models.CharField(max_length=60, blank=True, null=True)
    email = models.CharField(max_length=40, blank=True, null=True)
    token = models.CharField(max_length=200, blank=True, null=True)
    ruta = models.CharField(max_length=200, blank=True, null=True)
    notas = models.CharField(max_length=20, blank=True, null=True)
    tam_boleta = models.CharField(max_length=8, blank=True, null=True)
    tam_factura = models.CharField(max_length=8, blank=True, null=True)
    tam_pedido = models.CharField(max_length=8, blank=True, null=True)
    empresa = models.ForeignKey(Empresa, on_delete=models.PROTECT, default=1)

    class Meta:
        #managed = False
        db_table = 'sucursal'


class Personal(models.Model):
    idpersonal = models.AutoField(primary_key=True)
    nombre = models.CharField(max_length=40, blank=True, null=True)
    direccion = models.CharField(max_length=40, blank=True, null=True)
    tipodocumento = models.CharField(max_length=1, blank=True, null=True)
    documento = models.CharField(max_length=20, blank=True, null=True)
    fecha_ingreso = models.DateField(blank=True, null=True, default=timezone.now)
    notas = models.CharField(max_length=50, blank=True, null=True)
    cargo = models.CharField(max_length=3, blank=True, null=True)
    celular = models.CharField(max_length=15, blank=True, null=True)
    activo = models.CharField(max_length=1, blank=True, null=True, default="1")
    idusuario = models.OneToOneField(User, on_delete=models.PROTECT,null=True, blank=True)
    idsucursal = models.ForeignKey(Sucursal, on_delete=models.PROTECT,default=1,blank=True, null=True)

    class Meta:
        #managed = False
        db_table = 'personal'

    def __str__(self):
        return f"Personal:  {self.idpersonal} - {self.nombre}"
       


class Aprobador(models.Model):
    codigo = models.CharField(max_length=50, unique=True)
    nombre = models.TextField(null=True, blank=True)
    cargo = models.CharField(max_length=100, blank=True, null=True)
    idusuario = models.OneToOneField(User, on_delete=models.SET_NULL, null=True, blank=True)

    def __str__(self):
        return self.nombre


class Banco(models.Model):
    id_banco = models.AutoField(primary_key=True)
    nombre = models.CharField(max_length=100)
    codigo_sunat = models.CharField(max_length=10, null=True, blank=True)

    class Meta:
        db_table = 'banco'

    def __str__(self):
        return self.nombre


class Departamento(models.Model):
    id_departamento = models.AutoField(primary_key=True)
    nombre = models.CharField(max_length=100)

    class Meta:
        db_table = 'departamento'

    def __str__(self):
        return self.nombre


class Cargo(models.Model):
    id_cargo = models.AutoField(primary_key=True)
    nombre = models.CharField(max_length=100)

    class Meta:
        db_table = 'cargo'

    def __str__(self):
        return self.nombre


class TasaGeneral(models.Model):
    id_tasaGeneral = models.AutoField(primary_key=True)
    nombre = models.CharField(max_length=70)
    porcentaje = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    class Meta:
        db_table = 'tasa_general'

    def __str__(self):
        return self.nombre

class RegimenPensionario(models.Model):
    TIPO_CHOICES = [
        ('AFP', 'AFP'),
        ('ONP', 'ONP'),
    ]
    id_afp = models.AutoField(primary_key=True)
    nombre = models.CharField(max_length=100)
    tipo = models.CharField(max_length=3, choices=TIPO_CHOICES)

    class Meta:
        db_table = 'regimen_pensionario'

    def __str__(self):
        return f"{self.nombre} ({self.tipo})"


class AfpTasasMensuales(models.Model):
    id_tasa = models.AutoField(primary_key=True)
    afp = models.ForeignKey(RegimenPensionario, on_delete=models.RESTRICT, db_column='id_afp')
    periodo = models.CharField(max_length=7) # Formato YYYY-MM
    comision_sobre_flujo = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    comision_anual_sobre_saldo = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    prima_de_seguro = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    aporte_obligatorio = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    remuneracion_maxima_asegurable = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    class Meta:
        db_table = 'afp_tasas_mensuales'
        unique_together = ('afp', 'periodo')
    def __str__(self):
        return f"{self.afp.nombre} - {self.periodo}"


class Empleado(models.Model):
    id_empleado = models.AutoField(primary_key=True)
    cargo = models.ForeignKey(Cargo, on_delete=models.RESTRICT, db_column='id_cargo')
    departamento = models.ForeignKey(Departamento, on_delete=models.RESTRICT, db_column='id_departamento')
    afp = models.ForeignKey(RegimenPensionario, on_delete=models.RESTRICT, db_column='id_afp')
    banco = models.ForeignKey(Banco, on_delete=models.SET_NULL, null=True, blank=True, db_column='id_banco')
    dni = models.CharField(max_length=15, unique=True)
    apellido_paterno = models.CharField(max_length=100)
    apellido_materno = models.CharField(max_length=100)
    nombres = models.CharField(max_length=100)
    fecha_ingreso = models.DateField()
    fecha_cese = models.DateField(null=True, blank=True)
    asignacion_familiar = models.DecimalField(max_digits=10,null=True ,decimal_places=2)
    cuspp = models.CharField(max_length=25, null=True, blank=True)
    jornal_diario = models.DecimalField(max_digits=10, decimal_places=2)
    nro_cuenta = models.CharField(max_length=50, null=True, blank=True)
    tipo_situacion = [
        ('CONTRATADO', 'CONTRATADO'),
        ('ESTABLE', 'ESTABLE'),
    ]
    situacion = models.CharField(max_length=15, choices=tipo_situacion, default='CONTRATADO')
    tipo_categoria = [
        ('EMPLEADO', 'EMPLEADO'),
        ('OBRERO', 'OBRERO'),
    ]
    categoria = models.CharField(max_length=10, choices=tipo_categoria, default='OBRERO')
    tipo_estadocivil = [
        ('SOLTERO', 'SOLTERO'),
        ('CASADO', 'CASADO'),
        ('VIUDO', 'VIUDO'),
        ('DIVORCIADO', 'DIVORCIADO'),
    ]
    estadocivil = models.CharField(max_length=15, choices=tipo_estadocivil, default='SOLTERO')

    class Meta:
        db_table = 'empleado'

    def __str__(self):
        return f"{self.apellido_paterno} {self.apellido_materno}, {self.nombres}"


class Planilla(models.Model):
    id_planilla = models.AutoField(primary_key=True)
    periodo = models.CharField(max_length=7)
    fecha_inicio = models.DateField()
    fecha_fin = models.DateField()
    neto_pagar = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    descripcion = models.CharField(max_length=100) 
    tipo_clase = [
        ('ORDINARIA', 'ORDINARIA'),
        ('LIQUIDACION', 'LIQUIDACION'),
        ('CTS', 'CTS'),
        ('GRATIFICACION', 'GRATIFICACION'),
        ('VACACIONES', 'VACACIONES'),
    ]
    clase = models.CharField(max_length=13, choices=tipo_clase, default='ORDINARIA')
    
    tasa_pensionario = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    tasa_fcjmms = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    tasa_essalud = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    tasa_cstr = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    
    fecha_generacion = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'planilla'

    def __str__(self):
        return f"Planilla {self.periodo}"


class PlanillaDetalle(models.Model):
    id_detalle = models.AutoField(primary_key=True)
    planilla = models.ForeignKey(Planilla, on_delete=models.RESTRICT, db_column='id_planilla')
    empleado = models.ForeignKey(Empleado, on_delete=models.RESTRICT, db_column='id_empleado')
    id_tasa_afp = models.ForeignKey(AfpTasasMensuales, on_delete=models.SET_NULL, null=True, blank=True, db_column='id_tasa_afp')
    
    cargo = models.ForeignKey(Cargo, on_delete=models.RESTRICT, db_column='id_cargo', null=True, blank=True)
    departamento = models.ForeignKey(Departamento, on_delete=models.RESTRICT, db_column='id_departamento', null=True, blank=True)
    afp = models.ForeignKey(RegimenPensionario, on_delete=models.RESTRICT, db_column='id_afp', null=True, blank=True)
    cuspp = models.CharField(max_length=25, null=True, blank=True)
    
    fecha_ingreso = models.DateField(null=True, blank=True)
    fecha_cese = models.DateField(null=True, blank=True)
    fecha_inicio_vacaciones = models.DateField(null=True, blank=True)
    fecha_fin_vacaciones = models.DateField(null=True, blank=True)
    remuneracion_otro_empleador = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # DATOS BASE DEL MES
    jornal_diario = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    dias_trabajados = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    remuneracion_base = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_asignacion_familiar = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    total_remuneracion = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # DÍAS (Se usa max_digits=5 para reflejar DECIMAL(5,2))
    dias_libres_ganados = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_faltas_sin_goce = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_feriados = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_permiso_con_goce = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_licencia_pat_fall = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_descanso_medico = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_turno_dia = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_vacaciones = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    dias_compra_vacaciones = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    total_dias = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)

    # MONTO DE LOS DÍAS
    monto_libres_ganados = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_faltas_sin_goce = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_feriados = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_permiso_con_goce = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_licencia_pat_fall = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_compra_dias = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_vacaciones = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_compra_vacaciones = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_vacaciones_truncas = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_sobretasa = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    
    subtotal_montos = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    
    total_ingresos = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # DESCUENTOS
    monto_snp = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_afp = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_comision = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_prima = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_aporte = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_renta_5ta = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_fcjmms = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    adelantos = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    total_descuentos = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # NETO
    total_sueldo_neto = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # SALUD
    aplica_aporte_pensionario2 = models.BooleanField(default=False)
    aplica_comision_afp = models.BooleanField(default=False)
    aplica_fcjmms = models.BooleanField(default=False)
    aporte_essalud = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    aporte_pensionario_2 = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    cstr_salud = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    vida_ley = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    cstr_pensiones = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    total_salud = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # CONDICION TRABAJO
    bono_fijo_pasajes = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    otros_condicion = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    total_condicion_trabajo = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # OTROS
    cts = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    gratificaciones = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    bonificacion = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    total_otros = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # TOTAL A PAGAR LÍQUIDO
    total_a_pagar = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    # AUDITORÍA
    fecha_creacion_detalle = models.DateTimeField(auto_now_add=True)
    fecha_modificacion_detalle = models.DateTimeField(auto_now=True) 
    
    meses_computables_grat = models.DecimalField(max_digits=4, decimal_places=2, default=0.00)
    remuneracion_computable_grat = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    monto_bonif_extraordinaria = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    
    dias_computables_cts = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    meses_computables_cts = models.DecimalField(max_digits=4, decimal_places=2, default=0.00)
    remuneracion_computable_cts = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    sexto_gratificacion_cts = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    class Meta:
        db_table = 'planilla_detalle'

    def __str__(self):
        return f"Detalle de {self.empleado} - Planilla {self.planilla.periodo}"
    
    def actualizar_neto_planilla(self, planilla_referencia):
        resultado = PlanillaDetalle.objects.filter(planilla=planilla_referencia).aggregate(total=Sum('total_a_pagar'))
        suma_total = resultado['total'] or 0.00
        
        planilla_referencia.neto_pagar = suma_total
        planilla_referencia.save()
    
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        self.actualizar_neto_planilla(self.planilla)

    def delete(self, *args, **kwargs):
        planilla_relacionada = self.planilla
        super().delete(*args, **kwargs)
        self.actualizar_neto_planilla(planilla_relacionada)
        
class ConceptoContable(models.Model):
    id_concepto = models.AutoField(primary_key=True)
    campo_interno = models.CharField(max_length=50, unique=True)  # ej: 'total_a_pagar'
    etiqueta = models.CharField(max_length=100)                   # ej: 'Total a pagar'
    orden = models.PositiveSmallIntegerField(default=0)
    activo = models.BooleanField(default=True)

    class Meta:
        db_table = 'concepto_contable'
        ordering = ['orden']

    def __str__(self):
        return self.etiqueta


class CuentaContable(models.Model):
    TIPO_MOVIMIENTO = [
        ('DEBE', 'DEBE'),
        ('HABER', 'HABER'),
    ]
    id_cuenta = models.AutoField(primary_key=True)
      
    concepto = models.ForeignKey(ConceptoContable, on_delete=models.RESTRICT, db_column='id_concepto')
    
    departamento = models.ForeignKey(Departamento, on_delete=models.SET_NULL, null=True, blank=True, db_column='id_departamento')
    afp = models.ForeignKey(RegimenPensionario, on_delete=models.SET_NULL, null=True, blank=True, db_column='id_afp')
    
    codigo_cuenta = models.CharField(max_length=20)
    descripcion = models.CharField(max_length=150)
    tipo_movimiento = models.CharField(max_length=5, choices=TIPO_MOVIMIENTO)
    fecha_registro = models.DateTimeField(auto_now_add=True)
    fecha_modificacion = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'cuenta_contable'

    def __str__(self):
        return f"{self.codigo_cuenta} - {self.descripcion}"