from sqlalchemy import create_engine, Column, Integer, String, Boolean, Date, Time, ForeignKey, DateTime, Double, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session, relationship # Importar 'relationship' para las relaciones
from datetime import date, time, datetime

# --- Configuración de la Base de Datos (Mantener la tuya) ---

SQLALCHEMY_DATABASE_URL = "postgresql+psycopg2://tws2_user:B453*2wx9q.@localhost:5436/base_general"
#SQLALCHEMY_DATABASE_URL = "postgresql+psycopg2://postgres:0988@localhost:5432/acf"

# Crear el motor de la base de datos
# Configuración del 'search_path' para forzar a usar el esquema 'reservas_mesa'.
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, 
    connect_args={"options": "-csearch_path=reservas_mesa,public"}
) 

# Crear la clase base para los modelos
Base = declarative_base()

# Crear la sesión
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# Función para obtener la sesión de la base de datos
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


# --- Modelos SQLAlchemy ---

# 1. RESTAURANTE
class DBRestaurante(Base):
    __tablename__ = "restaurante"

    id = Column(Integer, primary_key=True, index=True)
    ruc = Column(String, unique=True, index=True) # UK
    nombre = Column(String)
    razon_social = Column(String)
    email = Column(String, unique=True) # UK
    whatsapp = Column(String, unique=True) # UK

    # Relación con SUCURSAL (Opcional: para usar 'relationship')
    sucursales = relationship("DBSucursal", back_populates="restaurante")


# 2. SUCURSAL
class DBSucursal(Base):
    __tablename__ = "sucursal"
    
    id = Column(Integer, primary_key=True, index=True)
    id_restaurante = Column(Integer, ForeignKey("restaurante.id"), index=True) # FK
    direccion = Column(String)
    ciudad = Column(String)

    # Relación con RESTAURANTE y MESA (Opcional: para usar 'relationship')
    restaurante = relationship("DBRestaurante", back_populates="sucursales")
    mesas = relationship("DBMesa", back_populates="sucursal")


# 3. MESA
class DBMesa(Base):
    __tablename__ = "mesa"

    id = Column(Integer, primary_key=True, index=True)
    id_sucursal = Column(Integer, ForeignKey("sucursal.id"), index=True) # FK
    identificador_mesa = Column(Integer) # Parece ser el número/identificador dentro de la sucursal
    capacidad = Column(Integer)
    ubicacion = Column(String)
    disponible = Column(Boolean, default=True)

    # Clave Única para id_sucursal y identificador_mesa (PK compuesta en el diagrama)
    __table_args__ = (
        UniqueConstraint('id_sucursal', 'identificador_mesa', name='uk_sucursal_mesa'),
    )

    # Relación con SUCURSAL y RESERVA (Opcional: para usar 'relationship')
    sucursal = relationship("DBSucursal", back_populates="mesas")
    reservas = relationship("DBReserva", back_populates="mesa")


# 4. CLIENTE
class DBCliente(Base):
    __tablename__ = "cliente" # Cambié de 'clientes' a 'cliente' para consistencia

    id = Column(Integer, primary_key=True, index=True)
    whatsapp = Column(String, unique=True, index=True) # UK
    nombre = Column(String)
    fecha_registro = Column(DateTime, default=datetime.now) # Usar DateTime para consistencia

    # Relación con RESERVA (Opcional: para usar 'relationship')
    reservas = relationship("DBReserva", back_populates="cliente")

# 5. RESERVA
class DBReserva(Base):
    __tablename__ = "reserva"

    id = Column(Integer, primary_key=True, index=True)
    id_sucursal = Column(Integer, ForeignKey("sucursal.id"), index=True) # FK
    id_cliente = Column(Integer, ForeignKey("cliente.id"), index=True) # FK
    id_mesa = Column(Integer, ForeignKey("mesa.id"), index=True) # FK
    fecha_registro = Column(DateTime, default=datetime.now)
    fecha_reserva = Column(DateTime)
    # El diagrama no tiene hora, pero en tu original sí, se mantiene por lógica
    # hora_reserva = Column(Time) 
    estado = Column(String) # E.g., 'PENDIENTE', 'CONFIRMADA', 'CANCELADA'

    # Relación con CLIENTE y MESA (Opcional: para usar 'relationship')
    cliente = relationship("DBCliente", back_populates="reservas")
    mesa = relationship("DBMesa", back_populates="reservas")


# 6. CONVERSACION
class DBConversacion(Base):
    __tablename__ = "conversacion"

    id = Column(Integer, primary_key=True, index=True)
    wamid = Column(String, unique=True, nullable=True) # UK
    mensaje = Column(String)
    whatsapp = Column(String)
    username = Column(String)
    origen = Column(String) # 'USUARIO | BOT'
    fecha = Column(DateTime, default=datetime.now)
    
# 7. CATEGORIA
class DBCategoria(Base):
    __tablename__ = "categoria"

    id = Column(Integer, primary_key=True, index=True)
    nombre = Column(String)
    posicion = Column(Integer) # Para el orden en el menú

    # Relación con PLATO (Opcional: para usar 'relationship')
    platos = relationship("DBPlato", back_populates="categoria")


# 8. PLATO
class DBPlato(Base):
    __tablename__ = "plato"

    id = Column(Integer, primary_key=True, index=True)
    id_categoria = Column(Integer, ForeignKey("categoria.id"), index=True) # FK
    nombre = Column(String)
    imagen = Column(String) # URL o ruta a la imagen
    precio_base = Column(Double) # Usar Double o Float
    disponible = Column(Boolean, default=True)

    # Relación con CATEGORIA y ITEM_MENU (Opcional: para usar 'relationship')
    categoria = relationship("DBCategoria", back_populates="platos")
    menu_items = relationship("DBItemMenu", back_populates="plato")


# 9. MENU
class DBMenu(Base):
    __tablename__ = "menu"

    id = Column(Integer, primary_key=True, index=True)
    nombre = Column(String)
    inicio = Column(DateTime) # Fecha/Hora de inicio de vigencia
    fin = Column(DateTime) # Fecha/Hora de fin de vigencia

    # Relación con ITEM_MENU (Opcional: para usar 'relationship')
    items = relationship("DBItemMenu", back_populates="menu")


# 10. ITEM_MENU (Tabla intermedia entre MENU y PLATO)
class DBItemMenu(Base):
    __tablename__ = "item_menu"

    id = Column(Integer, primary_key=True, index=True)
    id_menu = Column(Integer, ForeignKey("menu.id"), index=True) # FK
    id_plato = Column(Integer, ForeignKey("plato.id"), index=True) # FK
    posicion = Column(Integer)
    precio_especial = Column(Double, nullable=True) # Precio opcional para el menú

    # Clave Única para id_menu y id_plato (para no repetir platos en un menú)
    __table_args__ = (
        UniqueConstraint('id_menu', 'id_plato', name='uk_menu_plato'),
    )

    # Relación con MENU y PLATO (Opcional: para usar 'relationship')
    menu = relationship("DBMenu", back_populates="items")
    plato = relationship("DBPlato", back_populates="menu_items")


# --- Función para crear las tablas ---
def create_db_tables():
    Base.metadata.create_all(bind=engine)