from extensions import db
from sqlalchemy.dialects.postgresql import BOOLEAN, NUMERIC, ENUM
from sqlalchemy import Column, String, DateTime, Integer, Float, Text, Boolean
from werkzeug.security import generate_password_hash, check_password_hash
from sqlalchemy.sql import func
from datetime import datetime
from flask_login import UserMixin
import uuid

class OrdenesCompra1(db.Model):
    __tablename__ = 'OrdenesCompra1'

    Numero = db.Column(db.String(20), primary_key=True)
    FechaCreacion = db.Column(db.DateTime, nullable=False, default=func.now())
    IdUsuario = db.Column(db.String(15), db.ForeignKey('Usuarios.IdUsuario'), nullable=False)
    IdCliente = db.Column(db.String(20), db.ForeignKey('Clientes.IdCliente'), nullable=False)
    Observaciones = db.Column(db.String(500))
    OrdenCompletada = db.Column(db.Boolean, nullable=False, default=False)
    IdBodega = db.Column(db.String(20))
    fechamodificacion = db.Column(db.DateTime, onupdate=func.now())
    moneda = db.Column(db.Integer)
    IdConsecutivo = db.Column(db.Integer, nullable=False, default=20)
    IdCentroCosto = db.Column(db.String(10))
    Solicita = db.Column(db.String(100))
    Aprueba = db.Column(db.String(100))
    Estado = db.Column(db.String(20), nullable=False, default='Creada')
    TiempoPreparacion = db.Column(db.Integer)  # En segundos
    HoraEntrega = db.Column(db.DateTime)
    HoraRecogida = db.Column(db.DateTime)
    Direccion = db.Column(db.String(200))
    FechaInicioPrepanota = db.Column(db.DateTime)
    FechaFinPrepanota = db.Column(db.DateTime)

    # Relación con OrdenesCompra2
    detalles = db.relationship('OrdenesCompra2', backref='orden', lazy=True)

    # Relación con Clientes
    cliente = db.relationship('Clientes', backref='ordenes', lazy='joined')


    def __repr__(self):
        return f'<OrdenCompra {self.Numero}>'

class Clientes(db.Model):
    __tablename__ = 'Clientes'

    IdCliente = db.Column(db.String(20), primary_key=True)
    TipoIdentificacion = db.Column(db.String(10), nullable=False)
    Nombre = db.Column(db.String(100), nullable=False)
    Direccion = db.Column(db.String(200))
    Telefono = db.Column(db.String(20))
    Email = db.Column(db.String(100))
    FechaCreacion = db.Column(db.DateTime, nullable=False, default=func.now())
    FechaModificacion = db.Column(db.DateTime, onupdate=func.now())

    def __repr__(self):
        return f'<Cliente {self.IdCliente}>'

def generate_short_id():
    return uuid.uuid4().hex[:25]  # Genera un ID de 25 caracteres

class OrdenesCompra2(db.Model):
    __tablename__ = 'OrdenesCompra2'

    ID = db.Column(db.String(25), primary_key=True, default=generate_short_id)
    Numero = db.Column(db.String(20), db.ForeignKey('OrdenesCompra1.Numero'), nullable=False)
    IdReferencia = db.Column(db.String(50), nullable=False)
    Descripcion = db.Column(db.String(500), nullable=False)
    CantidadPedida = db.Column(db.Numeric(14, 2), nullable=False, default=0)
    CantidadEntregada = db.Column(db.Numeric(14, 2), nullable=False, default=0)
    Valor = db.Column(db.Numeric(14, 2), nullable=False, default=0)
    Descuento = db.Column(db.Numeric(5, 2), nullable=False, default=0)
    Iva = db.Column(db.Numeric(5, 2), nullable=False, default=0)
    CantidadTotal = db.Column(db.Numeric(14, 2), nullable=False, default=0)
    IdCentroCosto = db.Column(db.String(10))
    aprobadoworkflow = db.Column(db.Integer)
    apruebaworkflow = db.Column(db.Boolean)
    cantidadinicial = db.Column(db.Numeric(14, 2))
    ultimogrupoaprueba = db.Column(db.Integer)
    idunidad = db.Column(db.String(10))
    ObservacionesRef = db.Column(db.String(500))

    def __repr__(self):
        return f'<DetalleOrdenCompra {self.ID}>'

class Entradas1(db.Model):
    __tablename__ = 'Entradas1'

    Numero = db.Column(db.String(15), primary_key=True)
    Mes = db.Column(db.String(6), nullable=False)
    Anulado = db.Column(BOOLEAN, nullable=False, default=False)
    IdBodega = db.Column(db.String(20), nullable=False)
    CuentaDebito = db.Column(db.String(50))
    CuentaCredito = db.Column(db.String(50))
    Observaciones = db.Column(db.String(500))
    FechaCreacion = db.Column(db.DateTime, nullable=False)
    IdUsuario = db.Column(db.String(15), nullable=False)
    Recibe = db.Column(db.String(50))
    IdProyecto = db.Column(db.String(50))
    fechamodificacion = db.Column(db.DateTime)
    IdConsecutivo = db.Column(db.Integer, nullable=False, default=15)
    op = db.Column(db.String(10))
    fecha = db.Column(db.Date)
    idcliente = db.Column(db.String(50))
    transmitido = db.Column(BOOLEAN)
    subtotal = db.Column(NUMERIC(14, 2), default=0)
    total_iva = db.Column(NUMERIC(14, 2), default=0)
    total_impoconsumo = db.Column(NUMERIC(14, 2), default=0)
    total_ipc = db.Column(NUMERIC(14, 2), default=0)
    total_ibua = db.Column(NUMERIC(14, 2), default=0)
    total_icui = db.Column(NUMERIC(14, 2), default=0)
    total = db.Column(NUMERIC(14, 2), default=0)

class Entradas2(db.Model):
    __tablename__ = 'Entradas2'

    ID = db.Column(db.String(50), primary_key=True)
    Numero = db.Column(db.String(15), db.ForeignKey('Entradas1.Numero'), nullable=False)
    IdReferencia = db.Column(db.String(50), nullable=False)
    Descripcion = db.Column(db.String(500), nullable=False)
    Cantidad = db.Column(NUMERIC(14, 2), nullable=False, default=0)
    Valor = db.Column(NUMERIC(14, 2), nullable=False)
    IVA = db.Column(NUMERIC(8, 2), nullable=False, default=0)
    Descuento = db.Column(NUMERIC(14, 2), nullable=False, default=0)
    remision = db.Column(db.String(15))
    idfuente = db.Column(db.String(30))
    lote = db.Column(db.Text)
    idunidad = db.Column(db.Text)
    impoconsumo = db.Column(NUMERIC(14, 2), default=0)
    ipc = db.Column(NUMERIC(14, 2), default=0)
    imp_ibua = db.Column(NUMERIC(14, 2), default=0)
    imp_icui = db.Column(NUMERIC(14, 2), default=0)

class Salidas1(db.Model):
    __tablename__ = 'Salidas1'

    Numero = db.Column(db.String(15), primary_key=True)
    Mes = db.Column(db.String(6), nullable=False)
    Anulado = db.Column(BOOLEAN, nullable=False)
    IdBodega = db.Column(db.String(20), db.ForeignKey('Bodegas.IdBodega'), nullable=False)
    CuentaDebito = db.Column(db.String(50))
    CuentaCredito = db.Column(db.String(50))
    Observaciones = db.Column(db.String(500))
    FechaCreacion = db.Column(db.DateTime, nullable=False)
    IdUsuario = db.Column(db.String(15), db.ForeignKey('Usuarios.IdUsuario'), nullable=False)
    Recibe = db.Column(db.Text)
    idproyecto = db.Column(db.String(50))
    fechamodificacion = db.Column(db.DateTime)
    IdConsecutivo = db.Column(db.Integer, nullable=False, default=14)
    op = db.Column(db.String(10))
    fecha = db.Column(db.Date)
    transmitido = db.Column(BOOLEAN)
    numtraslado = db.Column(db.Text)
    subtotal = db.Column(NUMERIC(14, 2), default=0)
    total_iva = db.Column(NUMERIC(14, 2), default=0)
    total_impoconsumo = db.Column(NUMERIC(14, 2), default=0)
    total_ipc = db.Column(NUMERIC(14, 2), default=0)
    total_ibua = db.Column(NUMERIC(14, 2), default=0)
    total_icui = db.Column(NUMERIC(14, 2), default=0)
    total = db.Column(NUMERIC(14, 2), default=0)

class Salidas2(db.Model):
    __tablename__ = 'Salidas2'

    ID = db.Column(db.String(50), primary_key=True)
    Numero = db.Column(db.String(15), db.ForeignKey('Salidas1.Numero'), nullable=False)
    IdReferencia = db.Column(db.String(50), db.ForeignKey('Referencias.IdReferencia'), nullable=False)
    Descripcion = db.Column(db.String(500), nullable=False)
    Cantidad = db.Column(NUMERIC(14, 2), nullable=False)
    Valor = db.Column(NUMERIC(14, 2), nullable=False)
    IVA = db.Column(NUMERIC(8, 2), nullable=False)
    Descuento = db.Column(NUMERIC(14, 2), nullable=False)
    lote = db.Column(db.Text)
    idunidad = db.Column(db.Text)
    impoconsumo = db.Column(NUMERIC(14, 2), default=0)
    ipc = db.Column(NUMERIC(14, 2), default=0)
    imp_ibua = db.Column(NUMERIC(14, 2), default=0)
    imp_icui = db.Column(NUMERIC(14, 2), default=0)

# Asumimos que estas tablas ya existen o se crearán más tarde
class Proveedores(db.Model):
    __tablename__ = 'Proveedores'
    Nit = db.Column(db.String(50), primary_key=True)

class Usuarios(UserMixin, db.Model):
    __tablename__ = 'Usuarios'
   
    IdUsuario = db.Column(db.String(15), primary_key=True)
    Nombre = db.Column(db.String(100), nullable=False)
    Apellido = db.Column(db.String(100), nullable=False)
    Email = db.Column(db.String(120), unique=True, nullable=False)
    Password = db.Column(db.String(20), nullable=False)
    Rol = db.Column(db.Enum('administrador', 'coordinador', 'bodeguero', 'conductor', 'desarrollador_evento', 'generico', name='roles_usuario'), nullable=False)
    Activo = db.Column(db.Boolean, default=True, nullable=False)
    FechaCreacion = db.Column(db.DateTime, server_default=db.func.now())
    UltimoAcceso = db.Column(db.DateTime)
    Telefono = db.Column(db.String(20))
    Direccion = db.Column(db.String(200))
    codigo_verificacion = db.Column(db.String(6), nullable=True)

    def get_id(self):
        return str(self.IdUsuario)

    @property
    def is_active(self):
        return self.Activo

    def __repr__(self):
        return f'<Usuario {self.Nombre} {self.Apellido}>'

class Bodegas(db.Model):
    __tablename__ = 'Bodegas'
    IdBodega = db.Column(db.String(20), primary_key=True)

class Referencias(db.Model):
    __tablename__ = 'Referencias'

    IdReferencia = Column(String(50), primary_key=True)
    Referencia = Column(String(500), nullable=False)
    IdGrupo = Column(String(10), nullable=False)
    IdUnidad = Column(String(10), nullable=False)
    FechaCreacion = Column(DateTime, nullable=False, default=datetime.utcnow)
    Ubicacion = Column(String(30))
    IdCentroCosto = Column(String(10))
    Estado = Column(BOOLEAN, nullable=False, default=True)
    Tipo = Column(BOOLEAN, nullable=False, default=False)
    ReferenciaProveedor = Column(String(500))
    IVA = Column(NUMERIC(4, 2), default=0)
    Descuento = Column(NUMERIC(8, 2), default=0)
    Costo = Column(NUMERIC(14, 2), default=0)
    PrecioVenta1 = Column(NUMERIC(14, 2), default=0)
    Desde1 = Column(Integer, nullable=False, default=0)
    Hasta1 = Column(Integer, nullable=False, default=0)
    idsubgrupo = Column(String(10))
    impoconsumo = Column(NUMERIC(2, 0))
    porcpreciov1 = Column(Float)
    calcularprecioventa = Column(BOOLEAN)
    idgrupocaracteristica = Column(String(10))
    productoagotado = Column(BOOLEAN)
    ordengrupo = Column(Integer)
    costoreal = Column(NUMERIC(14, 2), default=0)
    idbodega = Column(Text)
    manejalotes = Column(BOOLEAN)
    metodolote = Column(Text)
    manejavencimiento = Column(BOOLEAN)
    ipc = Column(NUMERIC(14, 2), default=0)
    imp_ibua = Column(NUMERIC(14, 2), default=0)
    imp_icui = Column(NUMERIC(14, 2), default=0)
    imp_ibua_ml = Column(NUMERIC(14, 2), default=0)
    imp_ibua_tarifa = Column(NUMERIC(14, 2), default=0)
    idsubcategoria = Column(Text)
    Observaciones = Column(Text)

    def __repr__(self):
        return f'<Referencia {self.IdReferencia}>'

class Licencia(db.Model):
    __tablename__ = 'licencia'
    id = Column(Text, primary_key=True)
    razonsocial = Column(Text, nullable=False)
    nombrecomercial = Column(Text, nullable=False)
    fecha = Column(DateTime, default=func.now())
    ubicacioncomercial = Column(Text, nullable=False)
    ciudad = Column(Text, nullable=False)
    telefono = Column(Text, nullable=False)
    version = Column(Text, nullable=False)
    numerolicencia = Column(Text, nullable=False, unique=True)
    cantidadusuario = Column(Integer, nullable=False)
    numerofacturacompra = Column(Text)
    fechacompra = Column(DateTime)
    fechavencimiento = Column(DateTime)
    nit = Column(Text, nullable=False)
    tipolicencia = Column(Text, nullable=False)

class Consecutivos(db.Model):
    __tablename__ = 'Consecutivos'
    
    IdConsecutivo = Column(Integer, primary_key=True, autoincrement=False)
    Consecutivo = Column(String(50), nullable=False)
    Formulario = Column(String(3), nullable=False)
    Prefijo = Column(String(5), nullable=False)
    Desde = Column(String(10), nullable=False)
    Hasta = Column(String(10), nullable=False)
    Actual = Column(String(10), nullable=False)
    Resolucion = Column(String(15))
    FechaResolucion = Column(DateTime)
    ObservacionesResolucion = Column(Text)
    Estado = Column(Boolean, nullable=False, default=True)
    Comprobante = Column(String(20))
    Predeterminado = Column(Integer)
    fechafinresolucion = Column(Text)
    tiporesolucion = Column(String(20))

    def __repr__(self):
        return f'<Consecutivo {self.IdConsecutivo}>'

class Grupo(db.Model):
    __tablename__ = 'Grupos'
    IdGrupo = Column(String(10), primary_key=True)
    Grupo = Column(String(50), nullable=False)
    Estado = Column(Boolean, nullable=False)
    inventario = Column(Text)
    menupos = Column(Boolean, default=None)
    ultimoCodigo = db.Column(db.Integer, default=0)

class Unidades(db.Model):
    __tablename__ = 'Unidades'
    IdUnidad = Column(String(10), primary_key=True)
    Unidad = Column(String(50), nullable=False)
    Estado = Column(Boolean, default=True)