import os
from tokenize import String
from xml.dom.minidom import Text
from dotenv import load_dotenv
from flask import Flask, request, jsonify, send_from_directory
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from werkzeug.security import check_password_hash
from flask_jwt_extended import create_access_token, JWTManager, jwt_required, get_jwt, get_jwt_identity
from werkzeug.security import generate_password_hash
from sqlalchemy import Numeric
from datetime import timedelta, datetime, timezone
from sqlalchemy.sql import func
from werkzeug.utils import secure_filename
import uuid
import re

app = Flask(__name__)

load_dotenv()

## ——— Variables de entorno ———
USUARIO = os.getenv("USUARIO")
PASSWORD = os.getenv("PASSWORD")
HOST = os.getenv("HOST")
PORT = os.getenv("PORT")
DATABASE = os.getenv("DATABASE")

# Habilitar CORS para todas las rutas
CORS(
    app,
    resources={r"/*": {"origins": [
        "http://localhost:3000",
        "http://127.0.0.1:3000",
    ]}},
    supports_credentials=True,
    allow_headers=["Content-Type", "Authorization"],
    methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
)

# 🔹 Configuración de conexión a MySQL en XAMPP
# usuario: root | password: vacío (por defecto en XAMPP) | host: localhost | bd: mi_basedatos
app.config["JWT_SECRET_KEY"] = os.getenv("JWT_SECRET_KEY")
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://"+USUARIO+":"+PASSWORD+"@"+HOST+":"+PORT+"/"+DATABASE+""
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {
    "pool_pre_ping": True,        # valida conexión antes de usarla
    "pool_recycle": 280,          # recicla antes de wait_timeout típico
    "pool_size": 10,
    "max_overflow": 20,
    "connect_args": {"connect_timeout": 10},
}

# SERVIR ARCHIVOS UPLOADS
@app.route("/uploads/<path:filename>")
def uploaded_file(filename):

    return send_from_directory(
        "uploads",
        filename
    )


db = SQLAlchemy(app)
jwt = JWTManager(app)
UPLOAD_FOLDER = "uploads"
# ====================================================
# Login de app
# ====================================================

@app.route("/api/auth/login", methods=['POST'])
def login():
    data = request.get_json() or {}
    email = data.get("email")
    contrasena = data.get("password")

    if not email or not contrasena:
        return jsonify({"message": "Email y contraseña son obligatorios"}), 400

    user = Usuarios.query.filter_by(email=email).first()
    if not user:
        return jsonify({"message": "Usuario no encontrado"}), 404

    # Verificar contraseña con werkzeug
    if not check_password_hash(user.password_hash, contrasena):
        return jsonify({"message": "Credenciales inválidas", "contrasena": user.password_hash, "ingresada": contrasena}), 401

    # Claims del JWT: incluir nombre del usuario
    additional_claims = {
        "role": user.rol_id,
        "name": user.nombre,
        "nombre_rol": user.rol.nombre if user.rol else None
    }


    # Generar token (válido por 1 día) incluyendo los claims con el nombre
    access_token = create_access_token(
        identity=str(user.id),
        additional_claims=additional_claims,
        expires_delta=timedelta(days=1)
    )

    # Devolver token y opcionalmente el nombre para uso inmediato en frontend
    return jsonify({"message": "Login exitoso", "token": access_token}), 200

@app.route("/api/auth/login-empleado", methods=['POST'])
def login_empleado():

    data = request.get_json() or {}

    rfc = (
        data.get("rfc", "")
        .upper()
        .strip()
    )

    if not rfc:
        return jsonify({
            "message": "RFC obligatorio"
        }), 400

    empleado = Empleados_empresa.query.filter_by(
        rfc=rfc
    ).first()
    
    rfc_regex = r"^([A-ZÑ&]{3,4})\d{6}([A-Z\d]{3})?$"
    if not re.match(rfc_regex, rfc):

        return jsonify({"message": "RFC inválido"}), 400

    if not empleado:

        return jsonify({"message": "RFC no encontrado"}), 404

    # JWT CLAIMS
    additional_claims = {

        "role": 4,
        "name": empleado.nombre,
        "rfc": empleado.rfc,
        "empleado_empresa_id": empleado.id,
        "empresa_id": empleado.empresa_id,
        "login_type": "empleado",
    }

    access_token = create_access_token(

        identity=f"empleado_{empleado.id}",
        additional_claims=additional_claims,
        expires_delta=timedelta(days=1)
    )

    return jsonify({
        "message": "Login exitoso",
        "token": access_token
    }), 200


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

# ====================================================
# Clases
# ====================================================

# Tabla usuarios
class Usuarios(db.Model):
    __tablename__ = "usuarios"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(150), nullable=False)
    email = db.Column(db.String(100), nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)
    activo = db.Column(db.Boolean, nullable=True, default=True)
    
    rol_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    rol = db.relationship("Roles", backref="usuarios", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
            "email": self.email,
            "password_hash": self.password_hash,
            "activo": self.activo,
            "rol_id": self.rol_id,
            "rol": self.rol.to_dict() if self.rol else None
        }
        
# Tabla roles
class Roles(db.Model):
    __tablename__ = "roles"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(50), nullable=False)

    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
        }

#Tabla pacientes
class Pacientes(db.Model):
    __tablename__ = "pacientes"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(100), nullable=False)
    telefono = db.Column(db.String(20), nullable=True)
    correo = db.Column(db.String(100), nullable=False)
    fecha_nacimiento = db.Column(db.Date, nullable=True)
    observaciones = db.Column(db.Text, nullable=True)

    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
            "telefono": self.telefono,
            "correo": self.correo,
            "fecha_nacimiento": self.fecha_nacimiento.isoformat() if self.fecha_nacimiento else None,
            "observaciones": self.observaciones
        }
        
#Tabla expediente
class Expedientes(db.Model):
    __tablename__ = "expediente_clinico"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    fecha_creacion = db.Column(db.DateTime, nullable=False)

    paciente_id = db.Column(db.Integer, db.ForeignKey('pacientes.id'))
    paciente = db.relationship("Pacientes", backref="expedientes", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "fecha_creacion": self.fecha_creacion.isoformat(),
            "paciente_id": self.paciente_id
        }

#Tabla consultas
class Consultas(db.Model):
    __tablename__ = "consultas"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    fecha_consulta = db.Column(db.DateTime, nullable=False)
    motivo = db.Column(db.Text, nullable=True)
    diagnostico = db.Column(db.Text, nullable=True)
    tratamiento = db.Column(db.Text, nullable=True)
    notas = db.Column(db.Text, nullable=True)
    
    
    paciente_id = db.Column(db.Integer, db.ForeignKey('pacientes.id'))
    usuario_id = db.Column(db.Integer, db.ForeignKey('usuarios.id'))
    expediente_id = db.Column(db.Integer, db.ForeignKey('expediente_clinico.id'))
    paciente = db.relationship("Pacientes", backref="consultas", lazy=True)
    usuario = db.relationship("Usuarios", backref="consultas", lazy=True)
    expediente = db.relationship("Expedientes", backref="consultas", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "paciente_id": self.paciente_id,
            "usuario_id": self.usuario_id,
            "expediente_id": self.expediente_id,
            "fecha": self.fecha_consulta.isoformat(),
            "motivo": self.motivo,
            "diagnostico": self.diagnostico,
            "tratamiento": self.tratamiento,
            "notas": self.notas,
            # ADJUNTOS
            "consulta_adjuntos": [
                adj.to_dict()
                for adj in self.consulta_adjuntos
            ]
        }
        
#Tabla consultas adjuntos
class Consulta_adjuntos(db.Model):
    __tablename__ = "consulta_adjuntos"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    archivo_url = db.Column(db.String(255), nullable=False)
    tipo = db.Column(db.String(100), nullable=False)
    
    
    consulta_id = db.Column(db.Integer, db.ForeignKey('consultas.id'))
    consulta = db.relationship("Consultas", backref="consulta_adjuntos", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "archivo_url": self.archivo_url,
            "tipo": self.tipo,
            "consulta_id": self.consulta_id
        }

#Tabla Ventas
class Ventas(db.Model):
    __tablename__ = "ventas"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    fecha_pedido = db.Column(db.DateTime, nullable=False)
    estado = db.Column(db.String(50), nullable=False)
    observaciones = db.Column(db.Text, nullable=True)
    evidencia_url = db.Column(db.String(255), nullable=True)
    monto = db.Column(db.Numeric(10,2), nullable=False)
    cantidad = db.Column(db.Integer, nullable=False)
    
    
    paciente_id = db.Column(db.Integer, db.ForeignKey('pacientes.id'))
    empresa_id = db.Column(db.Integer, db.ForeignKey('empresa_cliente.id'))
    clinica_id = db.Column(db.Integer, db.ForeignKey('clinicas.id'))
    inventario_id = db.Column(db.Integer, db.ForeignKey('inventario.id'))
    
    paciente = db.relationship("Pacientes", backref="ventas", lazy=True)
    empresa = db.relationship("Empresa_cliente", backref="ventas", lazy=True)
    clinica = db.relationship("Clinicas", backref="ventas", lazy=True)
    inventario = db.relationship("Inventario", backref="ventas", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "fecha_pedido": self.fecha_pedido.isoformat(),
            "estado": self.estado,
            "observaciones": self.observaciones,
            "paciente_id": self.paciente_id,
            "empresa_id": self.empresa_id,
            "clinica_id": self.clinica_id,
            "clinica_nombre": (
                self.clinica.nombre
                if self.clinica else None
            ),
            "empresa_cliente_nombre": (self.empresa.nombre if self.empresa else None),
            "inventario_id": self.inventario_id,
            "inventario_clinica_id": (self.inventario.clinica_id if self.inventario else None),
            "evidencia_url": self.evidencia_url,
            "cantidad": self.cantidad,
            "monto": self.monto,
            
            "producto_nombre": (self.inventario.producto.nombre if self.inventario else None),
            "producto_precio_venta": (self.inventario.producto.precio_venta if self.inventario else None),
            "stock_disponible": (self.inventario.cantidad if self.inventario else None)
        }
        
#Tabla productos
class Productos(db.Model):
    __tablename__ = "productos"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(100), nullable=False)
    sku = db.Column(db.String(50), nullable=False, unique=True)
    precio_compra = db.Column(db.Numeric(10,2), nullable=False)
    precio_venta = db.Column(db.Numeric(10,2), nullable=False)
    descripcion = db.Column(db.Text, nullable=True)
    activo = db.Column(db.Boolean, nullable=True, default=True)
    categoria_id = db.Column(db.Integer, db.ForeignKey('categorias.id'))
    categoria = db.relationship("Categorias", backref="productos", lazy=True)
    
    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
            "sku": self.sku,
            "precio_compra": self.precio_compra,
            "precio_venta": self.precio_venta,
            "descripcion": self.descripcion,
            "activo": self.activo,
            "categoria_id": self.categoria_id
        }

# Tabla categorias
class Categorias(db.Model):
    __tablename__ = "categorias"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(100), nullable=False)

    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
        }
        
#Tabla Movimientos de productos
class Movimientos_producto(db.Model):    
    __tablename__ = "movimientos_producto"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    tipo = db.Column(db.String(25), nullable=False)  # 'entrada' o 'salida'
    cantidad = db.Column(db.Integer, nullable=False)
    costo = db.Column(db.Numeric(10,2), nullable=False)
    precio_venta = db.Column(db.Numeric(10,2), nullable=False)
    fecha_movimiento = db.Column(db.DateTime, nullable=False)
    
    
    producto_id = db.Column(db.Integer, db.ForeignKey('productos.id'))
    paciente_id = db.Column(db.Integer, db.ForeignKey('pacientes.id'))
    inventario_id = db.Column(db.Integer, db.ForeignKey('inventario.id'))
    clinica_destino_id = db.Column(db.Integer, db.ForeignKey('clinicas.id'))  # Para salidas, indicar a qué farmacia o clínica se envió
    
    inventario = db.relationship("Inventario", backref="movimientos_producto", lazy=True)
    producto = db.relationship("Productos", backref="movimientos_producto", lazy=True)
    paciente = db.relationship("Pacientes", backref="movimientos_producto", lazy=True)
    clinica_destino = db.relationship("Clinicas", backref="movimientos_producto", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "tipo": self.tipo,
            "cantidad": self.cantidad,
            "costo": self.costo,
            "precio_venta": self.precio_venta,
            "fecha_movimiento": self.fecha_movimiento.isoformat(),
            "producto_id": self.producto_id,
            "paciente_id": self.paciente_id,
            "inventario_id": self.inventario_id,
            "clinica_destino_id": self.clinica_destino_id
        }
        
#Tabla Movimientos financiero
        
class MovimientoFinanciero(db.Model):
    __tablename__ = "movimientos_financieros"

    id = db.Column(db.Integer, primary_key=True, index=True)

    tipo = db.Column(db.String(20), nullable=False)
    origen = db.Column(db.String(50), nullable=False)

    monto = db.Column(db.Numeric(10, 2), nullable=False)

    metodo_pago = db.Column(db.String(30))
    motivo = db.Column(db.Text, nullable=False)

    fecha_movimiento = db.Column(db.DateTime, server_default=func.now())

    usuario_id = db.Column(db.Integer, db.ForeignKey("usuarios.id"))
    movimiento_producto_id = db.Column(db.Integer, db.ForeignKey("movimientos_producto.id"))
    venta_id = db.Column(db.Integer, db.ForeignKey("ventas.id"))
    empresa_id = db.Column(db.Integer, db.ForeignKey("empresa_cliente.id"))
    
    def to_dict(self):
        return {
            "id": self.id,
            "tipo": self.tipo,
            "origen": self.origen,
            "monto": str(self.monto),
            "metodo_pago": self.metodo_pago,
            "motivo": self.motivo,
            "fecha_movimiento": self.fecha_movimiento.isoformat(),
            "usuario_id": self.usuario_id,
            "movimiento_producto_id": self.movimiento_producto_id,
            "venta_id": self.venta_id,
            "empresa_id": self.empresa_id
        }
    
#Tabla Empresas clientes
class Empresa_cliente(db.Model):
    __tablename__ = "empresa_cliente"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(100), nullable=False)
    telefono = db.Column(db.String(20), nullable=True)
    activo = db.Column(db.Boolean, nullable=True, default=True)


    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
            "telefono": self.telefono,
            "activo": self.activo
        }
        
#Tabla empleados_empresa
class Empleados_empresa(db.Model):
    __tablename__ = "empleados_empresa"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(100), nullable=False)
    telefono = db.Column(db.String(20), nullable=True)
    rfc = db.Column(db.String(13), nullable=False, unique=True)
    
    empresa_id = db.Column(db.Integer, db.ForeignKey('empresa_cliente.id'))
    empresa = db.relationship("Empresa_cliente", backref="empleados_empresa", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
            "telefono": self.telefono,
            "rfc": self.rfc,
            "empresa_id": self.empresa_id
        }
        
# Tabla clinicas

class Clinicas(db.Model):
    __tablename__ = "clinicas"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    nombre = db.Column(db.String(150), nullable=False)
    direccion = db.Column(db.String(255), nullable=True)
    telefono = db.Column(db.String(20), nullable=True)
    activo = db.Column(db.Boolean, default=True)

    inventarios = db.relationship("Inventario", backref="clinica", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "nombre": self.nombre,
            "direccion": self.direccion,
            "telefono": self.telefono,
            "activo": self.activo
        }
        
# Tabla clinica_especialistas

class ClinicaEspecialistas(db.Model):
    __tablename__ = "clinica_especialistas"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    clinica_id = db.Column(db.Integer, db.ForeignKey("clinicas.id"), nullable=False)
    especialista_id = db.Column(db.Integer, db.ForeignKey("usuarios.id"), nullable=False)

    clinica = db.relationship("Clinicas",backref=db.backref("especialistas_asignados", lazy=True))
    especialista = db.relationship("Usuarios", backref=db.backref("clinicas_asignadas", lazy=True))

    def to_dict(self):
        return {
            "id": self.id,
            "clinica_id": self.clinica_id,
            "especialista_id": self.especialista_id
        }
        
# Tabla inventario
class Inventario(db.Model):
    __tablename__ = "inventario"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    clinica_id = db.Column(db.Integer, db.ForeignKey('clinicas.id'), nullable=False)
    producto_id = db.Column(db.Integer, db.ForeignKey('productos.id'), nullable=False)

    cantidad = db.Column(db.Integer, nullable=False, default=0)

    producto = db.relationship("Productos", backref="inventarios", lazy=True)

    def to_dict(self):
        return {
            "id": self.id,
            "clinica_id": self.clinica_id,
            "producto_id": self.producto_id,
            "cantidad": self.cantidad,
            "nombre": self.producto.nombre if self.producto else None,
            "precio": self.producto.precio_venta if self.producto else None
        }

# ====================================================
# Rutas GET
# ====================================================

#GET usuarios

@app.route("/usuarios", methods=["GET"])
@jwt_required()
def get_usuarios():
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    usuarios = Usuarios.query.all()
    return jsonify([e.to_dict() for e in usuarios]), 200

# GET roles

@app.route("/roles", methods=["GET"])
@jwt_required()
def get_roles():
    
    # verificar claims y roles desde token
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1", "2", "3", "4", "5"]:
    #     return jsonify({"message": "No autorizado"}), 403
    
    roles = Roles.query.all()
    return jsonify([e.to_dict() for e in roles]), 200

# GET pacientes

@app.route("/pacientes", methods=["GET"])
@jwt_required()
def get_pacientes():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    pacientes = Pacientes.query.all()
    return jsonify([e.to_dict() for e in pacientes]), 200

# GET expedientes

@app.route("/expedientes", methods=["GET"])
@jwt_required()
def get_expedientes():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    expedientes = Expedientes.query.all()
    return jsonify([e.to_dict() for e in expedientes]), 200

#Get Consultas

@app.route("/consultas", methods=["GET"])
@jwt_required()
def get_consultas():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    consultas = Consultas.query.all()
    return jsonify([e.to_dict() for e in consultas]), 200

#Get Consultas adjuntos

@app.route("/consulta_adjuntos", methods=["GET"])
@jwt_required()
def get_consulta_adjuntos():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    consulta_adjuntos = consulta_adjuntos.query.all()
    return jsonify([e.to_dict() for e in consulta_adjuntos]), 200

#GET productos

@app.route("/productos", methods=["GET"])
@jwt_required()
def get_productos():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    productos = Productos.query.all()
    return jsonify([e.to_dict() for e in productos]), 200

#GET categorias

@app.route("/categorias", methods=["GET"])
@jwt_required()
def get_categorias():
    
    # verificar claims y roles desde token
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1", "2", "3", "4", "5"]:
    #     return jsonify({"message": "No autorizado"}), 403
    
    categorias = Categorias.query.all()
    return jsonify([e.to_dict() for e in categorias]), 200

#GET movimientos de productos

@app.route("/movimientos_producto", methods=["GET"])
@jwt_required()
def get_movimientos_producto():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    movimientos = Movimientos_producto.query.all()
    return jsonify([e.to_dict() for e in movimientos]), 200

#GET movimientos financieros

@app.route("/movimientos_financieros", methods=["GET"])
@jwt_required()
def get_movimientos_financieros():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    
    movimientos = MovimientoFinanciero.query.all()
    return jsonify([e.to_dict() for e in movimientos]), 200

#GET ventas

@app.route("/ventas", methods=["GET"])
@jwt_required()
def get_ventas():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3", "4"]:
        return jsonify({"message": "No autorizado"}), 403
    
    pedidos = Ventas.query.all()
    return jsonify([e.to_dict() for e in pedidos]), 200

#GET empresas cliente

@app.route("/empresa_cliente", methods=["GET"])
@jwt_required()
def get_empresa_cliente():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3", "4"]:
        return jsonify({"message": "No autorizado"}), 403
    
    empresas = Empresa_cliente.query.all()
    return jsonify([e.to_dict() for e in empresas]), 200

@app.route("/empresa_cliente/<int:id>", methods=["GET"])
@jwt_required()
def get_empresa_productora(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401

    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    empresa = Empresa_cliente.query.get(id)

    if not empresa:
        return jsonify({"message": "Empresa no encontrada"}), 404

    return jsonify(empresa.to_dict()), 200

#GET empleados de empresa

@app.route("/empleados_empresa", methods=["GET"])
@jwt_required()
def get_empleados_empresa():
    
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    empleados = Empleados_empresa.query.all()
    print("Empleados encontrados:", empleados)  # Debug: cantidad de empleados encontrados
    return jsonify([e.to_dict() for e in empleados]), 200

# GET clinicas

@app.route("/clinicas", methods=["GET"])
@jwt_required()
def get_clinicas():
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3", "4"]:
        return jsonify({"message": "No autorizado"}), 403

    clinicas = Clinicas.query.all()
    return jsonify([e.to_dict() for e in clinicas]), 200

@app.route("/clinicas/<int:id>", methods=["GET"])
@jwt_required()
def get_clinica(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401

    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    clinica = Clinicas.query.get(id)

    if not clinica:
        return jsonify({"message": "Clínica no encontrada"}), 404

    return jsonify(clinica.to_dict()), 200

# GET clinica especialistas

@app.route("/clinicas/<int:id>/especialistas", methods=["GET"])
@jwt_required()
def get_clinica_especialistas(id):

    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None

    except Exception:
        return jsonify({
            "message": "Token inválido"
        }), 401

    if role not in ["1", "2", "3"]:
        return jsonify({
            "message": "No autorizado"
        }), 403

    asignaciones = ClinicaEspecialistas.query.filter_by(
        clinica_id=id
    ).all()

    usuarios = []

    for asignacion in asignaciones:

        usuario = asignacion.especialista

        if usuario:

            usuarios.append({
                "id": usuario.id,
                "asignacion_id": asignacion.id,
                "nombre": usuario.nombre,
                "email": usuario.email,
                "activo": usuario.activo,
                "rol": usuario.rol.to_dict()
            })

    return jsonify(usuarios), 200

# GET inventario

@app.route("/inventario", methods=["GET"])
@jwt_required()
def get_inventario():
    # verificar claims y roles desde token
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3", "4"]:
        return jsonify({"message": "No autorizado"}), 403

    inventario = Inventario.query.all()
    return jsonify([e.to_dict() for e in inventario]), 200

# ====================================================
# Rutas POST
# ====================================================

#POST usuario

@app.route("/usuarios", methods=["POST"])
@jwt_required()
def add_usuario():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token invalido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403
    
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()
    nuevo = Usuarios(
        nombre = data.get("nombre"),
        email = data.get("email"),
        password_hash = generate_password_hash(data.get("password")),
        activo = data.get("activo", True),
        rol_id = data.get("rol_id")
    )
    
    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al agregar el usuario"}), 500
    
    return jsonify({"message": "Usuario agregado"}), 201

#POST roles

@app.route("/roles", methods=["POST"])
@jwt_required()
def add_rol():
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1"]:
    #     return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()
    nuevo = Roles(
        nombre = data.get("nombre")
        )
    
    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al agregar el rol"}), 500
    
    return jsonify({"message": "Rol agregado"}), 201

#POST pacientes

@app.route("/pacientes", methods=["POST"])
@jwt_required()
def add_paciente():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Pacientes(
        nombre=data.get("nombre"),
        telefono=data.get("telefono"),
        correo=data.get("correo"),
        fecha_nacimiento=data.get("fecha_nacimiento"),
        observaciones=data.get("observaciones")
    )
    
    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al agregar el paciente"}), 500
    
    return jsonify({"message": "Paciente agregado"}), 201

#POST expedientes

@app.route("/expedientes", methods=["POST"])
@jwt_required()
def add_expediente():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Expedientes(
        paciente_id=data.get("paciente_id"),
        fecha_creacion=data.get("fecha_creacion")
    )
    
    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al agregar el expediente"}), 500
    
    return jsonify({"message": "Expediente agregado"}), 201

#POST consultas

@app.route("/consultas", methods=["POST"])
@jwt_required()
def add_consulta():

    try:

        claims = get_jwt()

        role = str(claims.get("role")) if claims else None

    except Exception:

        return jsonify({
            "message": "Token inválido"
        }), 401

    if role not in ["1", "2", "3"]:

        return jsonify({
            "message": "No autorizado"
        }), 403

    try:

        data = request.form

        paciente_id = data.get("paciente_id")

        expediente = Expedientes.query.filter_by(
            paciente_id=paciente_id
        ).first()

        # CREAR EXPEDIENTE AUTOMÁTICO
        if not expediente:

            expediente = Expedientes(
                fecha_creacion=datetime.now(timezone.utc),
                paciente_id=paciente_id
            )

            db.session.add(expediente)

            db.session.flush()

        # CREAR CONSULTA
        nuevo = Consultas(
            fecha_consulta=data.get("fecha_consulta"),
            motivo=data.get("motivo"),
            diagnostico=data.get("diagnostico"),
            tratamiento=data.get("tratamiento"),
            notas=data.get("notas"),
            paciente_id=paciente_id,
            usuario_id=claims.get("sub"),
            expediente_id=expediente.id,
        )

        db.session.add(nuevo)

        db.session.flush()

        # CREAR CARPETA SI NO EXISTE
        os.makedirs("uploads", exist_ok=True)

        # OBTENER ARCHIVOS
        archivos = request.files.getlist("archivos")

        for archivo in archivos:

            if archivo.filename == "":
                continue

            nombre_seguro = secure_filename(
                archivo.filename
            )

            extension = os.path.splitext(
                nombre_seguro
            )[1]

            nombre_final = (
                f"{uuid.uuid4()}{extension}"
            )

            ruta_fisica = os.path.join(
            "uploads",
            nombre_final
            )

            archivo.save(ruta_fisica)
    
            ruta_publica = f"/uploads/{nombre_final}"
    
            nuevo_adjunto = Consulta_adjuntos(
                archivo_url=ruta_publica,
                tipo=archivo.content_type,
                consulta_id=nuevo.id
            )

            db.session.add(nuevo_adjunto)

        db.session.commit()

        return jsonify({
            "message": "Consulta agregada"
        }), 201

    except Exception as e:

        db.session.rollback()

        print(
            "Error al agregar consulta:",
            e
        )

        return jsonify({
            "error": "Error al agregar la consulta"
        }), 500

#POST consultas adjuntos

@app.route("/consulta_adjuntos", methods=["POST"])
@jwt_required()
def add_consulta_adjuntos():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Consulta_adjuntos(
        archivo_url=data.get("archivo_url"),
        tipo=data.get("tipo"),
        consulta_id=data.get("consulta_id")
    )

    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al adjuntar el archivo"}), 500

    return jsonify({"message": "Archivo adjuntado"}), 201

#POST Ventas

@app.route("/ventas", methods=["POST"])
@jwt_required()
def add_pedido_lente():
    
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3", "4"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()
    
    if not data.get("empresa_id"):
        nuevo = Ventas(
        fecha_pedido=data.get("fecha_pedido"),
        estado=data.get("estado"),
        observaciones=data.get("observaciones"),
        paciente_id=data.get("paciente_id"),
        evidencia_url=data.get("evidencia_url"),
        cantidad=data.get("cantidad"),
        monto=data.get("monto"),
        clinica_id=data.get("clinica_id"),
        inventario_id=data.get("inventario_id"),
        empresa_id=None
        )

    if not data.get("paciente_id"):
        nuevo = Ventas(
        fecha_pedido=data.get("fecha_pedido"),
        estado=data.get("estado"),
        observaciones=data.get("observaciones"),
        empresa_id=data.get("empresa_id"),
        evidencia_url=data.get("evidencia_url"),
        cantidad=data.get("cantidad"),
        monto=data.get("monto"),
        clinica_id=data.get("clinica_id"),
        inventario_id=data.get("inventario_id"),
        paciente_id=None
        )
        
    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception as e:
        print("Error al agregar venta:", e)
        return jsonify({"error": "Error al agregar venta"}), 500
        
    
# ==================================================
# CREAR MOVIMIENTO DE PRODUCTO (RESERVACION)
# ==================================================

    if data.get("inventario_id"):

        try:
            movimiento_payload = {
                "tipo": "reservacion",
                "cantidad": data.get("cantidad"),
                "producto_id": data.get("producto_id"),
                "inventario_id": data.get("inventario_id"),
                "precio_venta": data.get("monto"),
                "fecha_movimiento": data.get("fecha_pedido"),
                "paciente_id": (data.get("paciente_id") if data.get("paciente_id") not in ["", None] else None
                ),
                "metodo_pago": data.get("metodo_pago"),
            }

            # reutilizar función internamente
            with app.test_request_context(
                "/movimientos_producto",
                method="POST",
                json=movimiento_payload,
                headers=dict(request.headers)
            ):
                add_movimiento_producto()

        except Exception as e:
            print("Error creando movimiento automático:", e)

    return jsonify({"message": "Venta agregada"}), 201

#POST productos

@app.route("/productos", methods=["POST"])
@jwt_required()
def add_producto():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Productos(
        nombre=data.get("nombre"),
        sku=data.get("sku"),
        precio_compra=data.get("precio_compra"),
        precio_venta=data.get("precio_venta"),
        descripcion=data.get("descripcion"),
        activo=data.get("activo", True),
        categoria_id=data.get("categoria_id")
    )

    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al agregar el producto"}), 500

    return jsonify({"message": "Producto agregado"}), 201

#POST categorias

@app.route("/categorias", methods=["POST"])
@jwt_required()
def add_categoria():    
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1", "2"]:
    #     return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Categorias(
        nombre=data.get("nombre")
    )

    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al crear la categoría"}), 500

    return jsonify({"message": "Categoría creada"}), 201

#POST movimientos de productos

@app.route("/movimientos_producto", methods=["POST"])
@jwt_required()
def add_movimiento_producto():

    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
        usuario_id = get_jwt_identity()

    except Exception:
        return jsonify({
            "message": "Token inválido"
        }), 401

    if role not in ["1", "2", "3"]:
        return jsonify({
            "message": "No autorizado"
        }), 403

    if not request.is_json:
        return jsonify({
            "error": "Content-Type debe ser application/json"
        }), 415

    data = request.get_json()

    try:

        tipo = data.get("tipo")

        cantidad = int(data.get("cantidad", 0))

        producto_id = data.get("producto_id")

        inventario_id = data.get("inventario_id")

        clinica_destino_id = data.get("clinica_destino_id")

        costo = data.get("costo")

        precio_venta = data.get("precio_venta")

        fecha_movimiento = data.get("fecha_movimiento")

        paciente_id = data.get("paciente_id")
        
        metodo_pago = data.get("metodo_pago")
        if cantidad <= 0:
            return jsonify({
                "error": "Cantidad inválida"
            }), 400

        inventario = None

        if inventario_id:
            inventario = Inventario.query.get(inventario_id)

        # ==================================================
        # SI NO EXISTE INVENTARIO Y ES INGRESO
        # ==================================================
        if not inventario and tipo == "ingreso":

            clinica_id = data.get("clinica_id")

            inventario = Inventario.query.filter_by(
                clinica_id=clinica_id,
                producto_id=producto_id
            ).first()

            if not inventario:

                inventario = Inventario(
                    clinica_id=clinica_id,
                    producto_id=producto_id,
                    cantidad=0
                )

                db.session.add(inventario)

                db.session.flush()

        if not inventario:
            return jsonify({
                "error": "Inventario no encontrado"
            }), 404

        # ==================================================
        # INGRESO
        # ==================================================
        if tipo == "ingreso":

            inventario.cantidad += cantidad

        # ==================================================
        # EGRESO
        # ==================================================
        elif tipo == "egreso":

            if inventario.cantidad < cantidad:
                return jsonify({
                    "error": "Stock insuficiente"
                }), 400

            inventario.cantidad -= cantidad

        # ==================================================
        # TRASLADO
        # ==================================================
        elif tipo == "traslado":

            if not clinica_destino_id:
                return jsonify({
                    "error": "Clínica destino requerida"
                }), 400

            if inventario.cantidad < cantidad:
                return jsonify({
                    "error": "Stock insuficiente para traslado"
                }), 400

            # descontar origen
            inventario.cantidad -= cantidad

            # buscar inventario destino
            inventario_destino = Inventario.query.filter_by(
                clinica_id=clinica_destino_id,
                producto_id=producto_id
            ).first()

            # crear si no existe
            if not inventario_destino:

                inventario_destino = Inventario(
                    clinica_id=clinica_destino_id,
                    producto_id=producto_id,
                    cantidad=0
                )

                db.session.add(inventario_destino)

                db.session.flush()

            # sumar destino
            inventario_destino.cantidad += cantidad

        else:
            return jsonify({
                "error": "Tipo inválido"
            }), 400

        # ==================================================
        # GUARDAR MOVIMIENTO PRODUCTO
        # ==================================================
        nuevo = Movimientos_producto(
            tipo=tipo,
            cantidad=cantidad,
            costo=costo,
            precio_venta=precio_venta,
            fecha_movimiento=fecha_movimiento,
            producto_id=producto_id,
            paciente_id=paciente_id,
            inventario_id=inventario.id
        )

        db.session.add(nuevo)

        # NECESARIO PARA OBTENER EL ID
        db.session.flush()

        # ==================================================
        # CREAR MOVIMIENTO FINANCIERO
        # ==================================================

        movimiento_financiero = None
        
        producto = Productos.query.get(producto_id)

        nombre_producto = (
            producto.nombre
            if producto
            else f"ID {producto_id}"
        )

        # ----------------------------------------------
        # INGRESO PRODUCTO = EGRESO DINERO
        # ----------------------------------------------
        if tipo == "ingreso" and costo:

            movimiento_financiero = MovimientoFinanciero(
                tipo="EGRESO",

                origen="Compra de producto",

                monto=float(costo) * cantidad,

                metodo_pago=metodo_pago,

                motivo=f"Compra de producto {nombre_producto}",

                fecha_movimiento=fecha_movimiento,

                usuario_id=usuario_id,

                movimiento_producto_id=nuevo.id
            )

        # ----------------------------------------------
        # EGRESO PRODUCTO = INGRESO DINERO
        # ----------------------------------------------
        elif tipo == "egreso" and precio_venta:

            movimiento_financiero = MovimientoFinanciero(
                tipo="INGRESO",

                origen="Venta de producto",

                monto=float(precio_venta) * cantidad,

                metodo_pago=metodo_pago,

                motivo=f"Venta de producto {nombre_producto}",

                fecha_movimiento=fecha_movimiento,

                usuario_id=usuario_id,

                movimiento_producto_id=nuevo.id
            )

        # guardar movimiento financiero
        if movimiento_financiero:

            db.session.add(movimiento_financiero)

        # ==================================================
        # COMMIT FINAL
        # ==================================================
        db.session.commit()

        return jsonify({
            "message": "Movimiento registrado correctamente"
        }), 201

    except Exception as e:

        db.session.rollback()

        print(e)

        return jsonify({
            "error": "Error al registrar movimiento"
        }), 500
        
#POST movimientos financieros

@app.route("/movimientos_financieros", methods=["POST"])
@jwt_required()
def add_movimiento_financiero():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401

    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415

    data = request.get_json()

    try:
        nuevo = MovimientoFinanciero(
            tipo=data.get("tipo"),
            origen=data.get("origen"),
            monto=data.get("monto"),
            metodo_pago=data.get("metodo_pago"),
            motivo=data.get("motivo"),
            fecha_movimiento=data.get("fecha_movimiento"),

            usuario_id=data.get("usuario_id"),
            movimiento_producto_id=data.get("movimiento_producto_id"),
            venta_id=data.get("venta_id"),
            empresa_id=data.get("empresa_id"),
        )

        db.session.add(nuevo)

        db.session.commit()

        return jsonify({
            "message": "Movimiento registrado correctamente"
        }), 201

    except Exception as e:
        db.session.rollback()

        print(e)

        return jsonify({
            "error": "Error al registrar movimiento"
        }), 500

#POST Empresas productoras de lentes

@app.route("/empresa_cliente", methods=["POST"])
@jwt_required()
def add_empresa():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Empresa_cliente(
        nombre=data.get("nombre"),
        telefono=data.get("telefono"),
        activo=data.get("activo", True)
    )

    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al agregar la empresa"}), 500

    return jsonify({"message": "Empresa agregada"}), 201

#POST empleados de empresa

@app.route("/empleados_empresa", methods=["POST"])
@jwt_required()
def add_empleado():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Empleados_empresa(
        nombre=data.get("nombre"),
        telefono=data.get("telefono"),
        empresa_id=data.get("empresa_id"),
        rfc=data.get("rfc"),
        activo=data.get("activo", True)
    )

    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        return jsonify({"error": "Error al agregar el empleado"}), 500

    return jsonify({"message": "Empleado agregado"}), 201

#POST clinicas

@app.route("/clinicas", methods=["POST"])
@jwt_required()
def add_clinica():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nueva = Clinicas(
        nombre=data.get("nombre"),
        direccion=data.get("direccion"),
        telefono=data.get("telefono"),
        activo=data.get("activo", True)
    )

    try:
        db.session.add(nueva)
        db.session.commit()
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al agregar la clínica"}), 500

    return jsonify({"message": "Clínica agregada"}), 201

# POST clinica especialista

@app.route("/clinicas/<int:id>/especialistas", methods=["POST"])
@jwt_required()
def add_clinica_especialista(id):

    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None

    except Exception:
        return jsonify({"message": "Token inválido"}), 401

    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({
            "error": "Content-Type debe ser application/json"
        }), 415

    data = request.get_json()

    especialista_id = data.get("especialista_id")

    if not especialista_id:
        return jsonify({
            "error": "especialista_id es requerido"
        }), 400

    # VALIDAR DUPLICADOS
    existente = ClinicaEspecialistas.query.filter_by(
        clinica_id=id,
        especialista_id=especialista_id
    ).first()

    if existente:
        return jsonify({
            "error": "El usuario ya está asignado"
        }), 400

    nueva = ClinicaEspecialistas(
        clinica_id=id,
        especialista_id=especialista_id
    )

    try:

        db.session.add(nueva)
        db.session.commit()

    except Exception as e:

        db.session.rollback()

        return jsonify({
            "error": str(e)
        }), 500

    return jsonify({
        "message": "Usuario asignado correctamente"
    }), 201

#POST inventario

@app.route("/inventario", methods=["POST"])
@jwt_required()
def add_inventario():
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    data = request.get_json()

    nuevo = Inventario(
        clinica_id=data.get("clinica_id"),
        producto_id=data.get("producto_id"),
        cantidad=data.get("cantidad", 0),
    )

    try:
        db.session.add(nuevo)
        db.session.commit()
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al agregar al inventario"}), 500

    return jsonify({"message": "Inventario agregado"}), 201

# ====================================================
# Rutas PUT
# ====================================================

#PUT usuarios

@app.route("/usuarios/<int:id>", methods=["PUT"])
@jwt_required()
def update_usuario(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    usuario = Usuarios.query.get(id)
    
    if not usuario:
        return jsonify({"error": "Usuario no encontrado"}), 404

    if "nombre" in data:
        usuario.nombre = data["nombre"]
    if "email" in data:
        usuario.email = data["email"]
    if "password" in data:
        usuario.password_hash = generate_password_hash(data["password"])
    if "rol_id" in data:
        nuevo_rol_id = data.get("rol_id")
        if str(nuevo_rol_id) != str(usuario.rol_id) and str(role) != "1":
            return jsonify({"message": "No autorizado para cambiar el rol"}), 403
        
    if "activo" in data:
        usuario.activo = data["activo"]
    
    try:
        db.session.commit()
        return jsonify({"message": "Usuario actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el usuario"}), 500

#PUT roles

@app.route("/roles/<int:id>", methods=["PUT"])
@jwt_required()
def update_rol(id):
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1", "2", "3"]:
    #     return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    rol = Roles.query.get(id)
    
    if not rol:
        return jsonify({"error": "Rol no encontrado"}), 404

    if "nombre" in data:
        rol.nombre = data["nombre"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Rol actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el rol"}), 500

#PUT expedientes

@app.route("/expedientes/<int:id>", methods=["PUT"])
@jwt_required()
def update_expediente(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    expediente = Expedientes.query.get(id)
    
    if not expediente:
        return jsonify({"error": "Expediente no encontrado"}), 404

    if "paciente_id" in data:
        expediente.paciente_id = data["paciente_id"]
    if "fecha_creacion" in data:
        expediente.fecha_creacion = data["fecha_creacion"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Expediente actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el expediente"}), 500

#PUT pacientes

@app.route("/pacientes/<int:id>", methods=["PUT"])
@jwt_required()
def update_paciente(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    paciente = Pacientes.query.get(id)
    
    if not paciente:
        return jsonify({"error": "Paciente no encontrado"}), 404

    if "nombre" in data:
        paciente.nombre = data["nombre"]
    if "telefono" in data:
        paciente.telefono = data["telefono"]
    if "correo" in data:
        paciente.correo = data["correo"]
    if "fecha_nacimiento" in data:
        paciente.fecha_nacimiento = data["fecha_nacimiento"]
    if "observaciones" in data:
        paciente.observaciones = data["observaciones"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Paciente actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el paciente"}), 500

#PUT consultas

@app.route("/consultas/<int:id>", methods=["PUT"])
@jwt_required()
def update_consulta(id):    
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    consulta = Consultas.query.get(id)
    
    if not consulta:
        return jsonify({"error": "Consulta no encontrada"}), 404

    if "fecha" in data:
        consulta.fecha = data["fecha"]
    if "observaciones" in data:
        consulta.observaciones = data["observaciones"]
    if "paciente_id" in data:
        consulta.paciente_id = data["paciente_id"]
    if "expediente_id" in data:
        consulta.expediente_id = data["expediente_id"]
    if "estado" in data:
        consulta.estado = data["estado"]
    if "motivo" in data:
        consulta.motivo = data["motivo"]
    if "diagnostico" in data:
        consulta.diagnostico = data["diagnostico"]
    if "tratamiento" in data:
        consulta.tratamiento = data["tratamiento"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Consulta actualizada"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar la consulta"}), 500

#PUT consulta adjuntos

@app.route("/consulta_adjuntos/<int:id>", methods=["PUT"])
@jwt_required()
def update_consulta_adjuntos(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    adjunto = Consulta_adjuntos.query.get(id)
    
    if not adjunto:
        return jsonify({"error": "Archivo adjunto no encontrado"}), 404

    if "archivo_url" in data:
        adjunto.archivo_url = data["archivo_url"]
    if "tipo" in data:
        adjunto.tipo = data["tipo"]
    if "consulta_id" in data:
        adjunto.consulta_id = data["consulta_id"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Archivo adjunto actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el archivo adjunto"}), 500

# PUT Ventas

@app.route("/ventas/<int:id>", methods=["PUT"])
def update_pedido_lente(id):

    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
# 
    # except Exception:
    #     return jsonify({
    #         "message": "Token inválido"
    #     }), 401
# 
    # if role not in ["1", "2", "3"]:
    #     return jsonify({
    #         "message": "No autorizado"
    #     }), 403

    pedido = Ventas.query.get(id)

    if not pedido:
        return jsonify({
            "error": "Pedido no encontrado"
        }), 404

    try:

        # FORM DATA
        data = request.form

        if "estado" in data:
            pedido.estado = data.get("estado")

        if "observaciones" in data:
            pedido.observaciones = data.get("observaciones")

        if "empresa_id" in data:
            pedido.empresa_id = data.get("empresa_id")

        if "paciente_id" in data:
            pedido.paciente_id = data.get("paciente_id")

        if "monto" in data:
            pedido.monto = data.get("monto")
            
        if "farmacia_id" in data:
            pedido.farmacia_id = data.get("farmacia_id")
            
        if "inventario_id" in data:
            pedido.inventario_id = data.get("inventario_id")

        # ARCHIVO
        evidencia = request.files.get("evidencia")

        if evidencia:

            filename = secure_filename(
                evidencia.filename
            )

            app.config["UPLOAD_FOLDER"] = os.path.join(os.getcwd(), "uploads")
            upload_folder = os.path.join(
                app.config["UPLOAD_FOLDER"],
                "ventas"
            )

            os.makedirs(
                upload_folder,
                exist_ok=True
            )

            filepath = os.path.join(
                upload_folder,
                filename
            )

            evidencia.save(filepath)

            pedido.evidencia_url = (
                f"/uploads/ventas/{filename}"
            )

        db.session.commit()

        return jsonify({
            "message": "Pedido actualizado correctamente"
        }), 200

    except Exception as e:

        db.session.rollback()

        print(e)

        return jsonify({
            "error": "Error al actualizar el pedido"
        }), 500

#PUT productos

@app.route("/productos/<int:id>", methods=["PUT"])
@jwt_required()
def update_producto(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    producto = Productos.query.get(id)
    
    if not producto:
        return jsonify({"error": "Producto no encontrado"}), 404

    if "nombre" in data:
        producto.nombre = data["nombre"]
    if "sku" in data:
        producto.sku = data["sku"]
    if "precio_compra" in data:
        producto.precio_compra = data["precio_compra"]
    if "precio_venta" in data:
        producto.precio_venta = data["precio_venta"]
    if "descripcion" in data:
        producto.descripcion = data["descripcion"]
    if "activo" in data:    
        producto.activo = data["activo"]
    if "categoria_id" in data:
        producto.categoria_id = data["categoria_id"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Producto actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el producto"}), 500

#PUT categorias

@app.route("/categorias/<int:id>", methods=["PUT"])
@jwt_required()
def update_categoria(id):
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1"]:
    #     return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    categoria = Categorias.query.get(id)
    
    if not categoria:
        return jsonify({"error": "Categoria no encontrada"}), 404

    if "nombre" in data:
        categoria.nombre = data["nombre"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Categoria actualizada"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar la categoria"}), 500

#PUT Movimientos de productos

@app.route("/movimientos_producto/<int:id>", methods=["PUT"])
@jwt_required()
def update_movimiento(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    movimiento = Movimientos_producto.query.get(id)
    
    if not movimiento:
        return jsonify({"error": "Movimiento no encontrado"}), 404

    if "fecha_movimiento" in data:
        movimiento.fecha_movimiento = data["fecha_movimiento"]
    if "cantidad" in data:
        movimiento.cantidad = data["cantidad"]
    if "costo" in data:
        movimiento.costo = data["costo"]
    if "precio_venta" in data:
        movimiento.precio_venta = data["precio_venta"]
    if "producto_id" in data:
        movimiento.producto_id = data["producto_id"]
    if "paciente_id" in data:
        movimiento.paciente_id = data["paciente_id"]
    if "inventario_id" in data:
        movimiento.inventario_id = data["inventario_id"]
    if "empresa_id" in data:
        movimiento.empresa_id = data["empresa_id"]
    if "clinica_destino_id" in data:
        movimiento.clinica_destino_id = data["clinica_destino_id"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Movimiento actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el movimiento"}), 500
    
#PUT movimientos financiero

@app.route("/movimientos_financieros/<int:id>", methods=["PUT"])
@jwt_required()
def update_movimiento_financiero(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    movimiento = MovimientoFinanciero.query.get(id)
    
    if not movimiento:
        return jsonify({"error": "Movimiento no encontrado"}), 404

    if "tipo" in data:
        movimiento.tipo = data["tipo"]

    if "origen" in data:
        movimiento.origen = data["origen"]

    if "monto" in data:
        movimiento.monto = data["monto"]

    if "metodo_pago" in data:
        movimiento.metodo_pago = data["metodo_pago"]

    if "motivo" in data:
        movimiento.motivo = data["motivo"]

    if "fecha_movimiento" in data:
        movimiento.fecha_movimiento = data["fecha_movimiento"]

    if "usuario_id" in data:
        movimiento.usuario_id = data["usuario_id"]

    if "movimiento_producto_id" in data:
        movimiento.movimiento_producto_id = data["movimiento_producto_id"]

    if "venta_id" in data:
        movimiento.venta_id = data["venta_id"]

    if "empresa_id" in data:
        movimiento.empresa_id = data["empresa_id"]

    try:

        db.session.commit()

        return jsonify({
            "message": "Movimiento financiero actualizado"
        }), 200

    except Exception as e:

        db.session.rollback()

        print(e)

        return jsonify({
            "error": "Error al actualizar el movimiento financiero"
        }), 500

#PUT empresas clientes

@app.route("/empresa_cliente/<int:id>", methods=["PUT"])
@jwt_required()
def update_empresa(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403
    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    empresa = Empresa_cliente.query.get(id)
    
    if not empresa:
        return jsonify({"error": "Empresa no encontrada"}), 404

    if "nombre" in data:
        empresa.nombre = data["nombre"]
    if "telefono" in data:
        empresa.telefono = data["telefono"]
    if "activo" in data:
        empresa.activo = data["activo"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Empresa actualizada"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar la empresa"}), 500

#PUT empleados de empresa

@app.route("/empleados_empresa/<int:id>", methods=["PUT"])
@jwt_required()
def update_empleado(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415
    
    data = request.get_json()
    print("DATA RECIBIDA:", data)
    empleado = Empleados_empresa.query.get(id)
    
    if not empleado:
        return jsonify({"error": "Empleado no encontrado"}), 404
    
    print(empleado)

    if "nombre" in data:
        empleado.nombre = data["nombre"]
    if "telefono" in data:
        empleado.telefono = data["telefono"]
    if "empresa_id" in data:
        empleado.empresa_id = data["empresa_id"]
    if "rfc" in data:
        empleado.rfc = data["rfc"]
        
    try:
        db.session.commit()
        return jsonify({"message": "Empleado actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el empleado"}), 500
    
# PUT clinicas

@app.route("/clinicas/<int:id>", methods=["PUT"])
@jwt_required()
def update_clinica(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415

    data = request.get_json()
    clinica = Clinicas.query.get(id)

    if not clinica:
        return jsonify({"error": "Clínica no encontrada"}), 404

    if "nombre" in data:
        clinica.nombre = data["nombre"]
    if "direccion" in data:
        clinica.direccion = data["direccion"]
    if "telefono" in data:
        clinica.telefono = data["telefono"]
    if "activo" in data:
        clinica.activo = data["activo"]

    try:
        db.session.commit()
        return jsonify({"message": "Clínica actualizada"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar la clínica"}), 500
    
# PUT inventario

@app.route("/inventario/<int:id>", methods=["PUT"])
@jwt_required()
def update_inventario(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    if not request.is_json:
        return jsonify({"error": "Content-Type debe ser application/json"}), 415

    data = request.get_json()
    inventario = Inventario.query.get(id)

    if not inventario:
        return jsonify({"error": "Inventario no encontrado"}), 404

    if "clinica_id" in data:
        inventario.clinica_id = data["clinica_id"]
    if "producto_id" in data:
        inventario.producto_id = data["producto_id"]
    if "cantidad" in data:
        inventario.cantidad = data["cantidad"]

    try:
        db.session.commit()
        return jsonify({"message": "Inventario actualizado"}), 200
    except Exception:
        db.session.rollback()
        return jsonify({"error": "Error al actualizar el inventario"}), 500

# ====================================================
# Rutas DELETE
# ====================================================

#DELETE usuarios

@app.route("/usuarios/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_usuario(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    usuario = Usuarios.query.get(id)
    if not usuario:
        return jsonify({"error": "Usuario no encontrado"}), 404
    db.session.delete(usuario)
    db.session.commit()
    return jsonify({"message": "Usuario eliminado"}), 200

#DELETE roles

@app.route("/roles/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_rol(id):
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1"]:
    #     return jsonify({"message": "No autorizado"}), 403

    rol = Roles.query.get(id)
    if not rol:
        return jsonify({"error": "Rol no encontrado"}), 404
    db.session.delete(rol)
    db.session.commit()
    return jsonify({"message": "Rol eliminado"}), 200

#DELETE pacientes

@app.route("/pacientes/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_paciente(id):    
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    paciente = Pacientes.query.get(id)
    if not paciente:
        return jsonify({"error": "Paciente no encontrado"}), 404
    db.session.delete(paciente)
    db.session.commit()
    return jsonify({"message": "Paciente eliminado"}), 200

#DELETE expedientes

@app.route("/expedientes/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_expediente(id):    
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    expediente = Expedientes.query.get(id)
    if not expediente:
        return jsonify({"error": "Expediente no encontrado"}), 404
    db.session.delete(expediente)
    db.session.commit()
    return jsonify({"message": "Expediente eliminado"}), 200

#DELETE consultas

# DELETE consulta
@app.route("/consultas/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_consulta(id):

    try:

        claims = get_jwt()
        role = str(claims.get("role")) if claims else None

    except Exception:

        return jsonify({
            "message": "Token inválido"
        }), 401

    if role not in ["1", "2", "3"]:

        return jsonify({
            "message": "No autorizado"
        }), 403

    consulta = Consultas.query.get(id)

    if not consulta:

        return jsonify({
            "error": "Consulta no encontrada"
        }), 404

    try:

        # ELIMINAR ARCHIVOS FÍSICOS
        for adjunto in consulta.consulta_adjuntos:

            ruta_archivo = adjunto.archivo_url.lstrip("/")

            if os.path.exists(ruta_archivo):
                os.remove(ruta_archivo)

            db.session.delete(adjunto)

        # ELIMINAR CONSULTA
        db.session.delete(consulta)

        db.session.commit()

        return jsonify({
            "message": "Consulta eliminada"
        }), 200

    except Exception as e:

        db.session.rollback()

        print("Error eliminando consulta:", e)

        return jsonify({
            "error": "Error eliminando consulta"
        }), 500

#DELETE consulta adjuntos

@app.route("/adjuntos/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_adjunto(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    adjunto = Consulta_adjuntos.query.get(id)
    if not adjunto:
        return jsonify({"error": "Archivo adjunto no encontrado"}), 404
    db.session.delete(adjunto)
    db.session.commit()
    return jsonify({"message": "Archivo adjunto eliminado"}), 200  

#DELETE Ventas

@app.route("/ventas/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_pedido_lente(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2", "3"]:
        return jsonify({"message": "No autorizado"}), 403

    pedido = Ventas.query.get(id)
    if not pedido:
        return jsonify({"error": "Pedido no encontrado"}), 404
    db.session.delete(pedido)
    db.session.commit()
    return jsonify({"message": "Pedido de lentes eliminado"}), 200

#DELETE productos

@app.route("/productos/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_producto(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    producto = Productos.query.get(id)
    if not producto:
        return jsonify({"error": "Producto no encontrado"}), 404
    db.session.delete(producto)
    db.session.commit()
    return jsonify({"message": "Producto eliminado"}), 200

#DELETE categorias

@app.route("/categorias/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_categoria(id):
    # try:
    #     claims = get_jwt()
    #     role = str(claims.get("role")) if claims else None
    # except Exception:
    #     return jsonify({"message": "Token inválido"}), 401
    # if role not in ["1"]:
    #     return jsonify({"message": "No autorizado"}), 403

    categoria = Categorias.query.get(id)
    if not categoria:
        return jsonify({"error": "Categoria no encontrada"}), 404
    db.session.delete(categoria)
    db.session.commit()
    return jsonify({"message": "Categoria eliminada"}), 200

#DELETE movimientos de productos

@app.route("/movimientos_producto/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_movimiento(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    movimiento = Movimientos_producto.query.get(id)
    if not movimiento:
        return jsonify({"error": "Movimiento no encontrado"}), 404
    db.session.delete(movimiento)
    db.session.commit()
    return jsonify({"message": "Movimiento eliminado"}), 200

#DELETE movimientos financieros

@app.route("/movimientos_financieros/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_movimiento_financiero(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    movimiento = MovimientoFinanciero.query.get(id)
    if not movimiento:
        return jsonify({"error": "Movimiento no encontrado"}), 404
    db.session.delete(movimiento)
    db.session.commit()
    return jsonify({"message": "Movimiento financiero eliminado"}), 200

#DELETE empresas productoras de lentes

@app.route("/empresa_cliente/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_empresa_lente(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    empresa = Empresa_cliente.query.get(id)
    if not empresa:
        return jsonify({"error": "Empresa no encontrada"}), 404
    db.session.delete(empresa)
    db.session.commit()
    return jsonify({"message": "Empresa eliminada"}), 200

#DELETE empleados de empresa

@app.route("/empleados_empresa/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_empleado(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    empleado = Empleados_empresa.query.get(id)
    if not empleado:
        return jsonify({"error": "Empleado no encontrado"}), 404
    db.session.delete(empleado)
    db.session.commit()
    return jsonify({"message": "Empleado eliminado"}), 200


# DELETE clinicas
@app.route("/clinicas/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_clinica(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    clinica = Clinicas.query.get(id)
    if not clinica:
        return jsonify({"error": "Clínica no encontrada"}), 404
    db.session.delete(clinica)
    db.session.commit()
    return jsonify({"message": "Clínica eliminada"}), 200

# DELETE clinica especialista
@app.route("/clinica_especialista/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_clinica_especialista(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1"]:
        return jsonify({"message": "No autorizado"}), 403

    clinica_especialista = ClinicaEspecialistas.query.get(id)
    if not clinica_especialista:
        return jsonify({"error": "Asignación de especialista no encontrada"}), 404
    db.session.delete(clinica_especialista)
    db.session.commit()
    return jsonify({"message": "Asignación de especialista eliminada"}), 200

# DELETE inventario

@app.route("/inventario/<int:id>", methods=["DELETE"])
@jwt_required()
def delete_inventario(id):
    try:
        claims = get_jwt()
        role = str(claims.get("role")) if claims else None
    except Exception:
        return jsonify({"message": "Token inválido"}), 401
    if role not in ["1", "2"]:
        return jsonify({"message": "No autorizado"}), 403

    inventario = Inventario.query.get(id)
    if not inventario:
        return jsonify({"error": "Inventario no encontrado"}), 404
    db.session.delete(inventario)
    db.session.commit()
    return jsonify({"message": "Inventario eliminado"}), 200
