# models.py - Modelos completos para webhooks de Rappi
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
import json

db = SQLAlchemy()

class WebhookEvent(db.Model):
    """Tabla para almacenar todos los eventos de webhook recibidos"""
    __tablename__ = 'WebhookEvents'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    evento_tipo = db.Column(db.String(50), nullable=False)  # NEW_ORDER, ORDER_EVENT_CANCEL, etc.
    signature = db.Column(db.String(255))  # Firma del webhook para validación
    datos_json = db.Column(db.Text, nullable=False)  # JSON completo del evento
    ip_origen = db.Column(db.String(45))  # IP desde donde llegó el webhook
    user_agent = db.Column(db.String(500))
    fecha_recepcion = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
    fecha_proceso = db.Column(db.DateTime)
    procesado = db.Column(db.Boolean, default=False, nullable=False)
    mensaje_proceso = db.Column(db.String(500))  # Mensaje de resultado del procesamiento
    
    def to_dict(self):
        return {
            'id': self.id,
            'evento_tipo': self.evento_tipo,
            'signature': self.signature,
            'datos_json': self.datos_json,
            'ip_origen': self.ip_origen,
            'user_agent': self.user_agent,
            'fecha_recepcion': self.fecha_recepcion.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_recepcion else None,
            'fecha_proceso': self.fecha_proceso.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_proceso else None,
            'procesado': self.procesado,
            'mensaje_proceso': self.mensaje_proceso
        }
    
    def get_datos_parsed(self):
        """Obtener los datos JSON parseados"""
        try:
            return json.loads(self.datos_json)
        except:
            return {}
    
    def __repr__(self):
        return f'<WebhookEvent {self.id}: {self.evento_tipo}>'

class RappiOrder(db.Model):
    """Tabla para almacenar órdenes específicas de Rappi"""
    __tablename__ = 'RappiOrders'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    order_id = db.Column(db.String(100), nullable=False, unique=True)  # ID único de Rappi
    
    # Información del cliente
    customer_name = db.Column(db.String(200))
    customer_phone = db.Column(db.String(20))
    customer_email = db.Column(db.String(100))
    
    # Información de la orden
    total_order = db.Column(db.Numeric(10, 2))
    delivery_fee = db.Column(db.Numeric(10, 2))
    service_fee = db.Column(db.Numeric(10, 2))
    tip = db.Column(db.Numeric(10, 2))
    
    # Estados y fechas
    estado = db.Column(db.String(50), default='pending')  # pending, accepted, rejected, ready, delivered, cancelled
    created_at = db.Column(db.String(50))  # Fecha de creación de Rappi (string)
    accepted_at = db.Column(db.DateTime)
    rejected_at = db.Column(db.DateTime)
    ready_at = db.Column(db.DateTime)
    delivered_at = db.Column(db.DateTime)
    cancelled_at = db.Column(db.DateTime)
    
    # Información adicional
    cooking_time = db.Column(db.Integer)  # Tiempo de cocción en minutos
    rejection_reason = db.Column(db.String(500))
    cancellation_reason = db.Column(db.String(500))
    
    # Dirección de entrega
    delivery_address = db.Column(db.String(500))
    delivery_city = db.Column(db.String(100))
    delivery_district = db.Column(db.String(100))
    delivery_instructions = db.Column(db.String(500))
    
    # Datos completos
    items_json = db.Column(db.Text)  # Items de la orden en JSON
    datos_completos = db.Column(db.Text)  # JSON completo de la orden
    
    # Referencias
    webhook_event_id = db.Column(db.Integer, db.ForeignKey('WebhookEvents.id'))
    
    # Metadatos
    fecha_creacion = db.Column(db.DateTime, default=datetime.utcnow)
    fecha_modificacion = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    usuario_modificacion = db.Column(db.String(100))
    
    # Relaciones
    webhook_event = db.relationship('WebhookEvent', backref='ordenes')
    
    def to_dict(self):
        return {
            'id': self.id,
            'order_id': self.order_id,
            'customer_name': self.customer_name,
            'customer_phone': self.customer_phone,
            'customer_email': self.customer_email,
            'total_order': float(self.total_order) if self.total_order else 0,
            'delivery_fee': float(self.delivery_fee) if self.delivery_fee else 0,
            'service_fee': float(self.service_fee) if self.service_fee else 0,
            'tip': float(self.tip) if self.tip else 0,
            'estado': self.estado,
            'created_at': self.created_at,
            'accepted_at': self.accepted_at.strftime('%Y-%m-%d %H:%M:%S') if self.accepted_at else None,
            'rejected_at': self.rejected_at.strftime('%Y-%m-%d %H:%M:%S') if self.rejected_at else None,
            'ready_at': self.ready_at.strftime('%Y-%m-%d %H:%M:%S') if self.ready_at else None,
            'delivered_at': self.delivered_at.strftime('%Y-%m-%d %H:%M:%S') if self.delivered_at else None,
            'cancelled_at': self.cancelled_at.strftime('%Y-%m-%d %H:%M:%S') if self.cancelled_at else None,
            'cooking_time': self.cooking_time,
            'rejection_reason': self.rejection_reason,
            'cancellation_reason': self.cancellation_reason,
            'delivery_address': self.delivery_address,
            'delivery_city': self.delivery_city,
            'delivery_district': self.delivery_district,
            'delivery_instructions': self.delivery_instructions,
            'fecha_creacion': self.fecha_creacion.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_creacion else None,
            'fecha_modificacion': self.fecha_modificacion.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_modificacion else None,
            'usuario_modificacion': self.usuario_modificacion,
            'webhook_event_id': self.webhook_event_id
        }
    
    def to_dict_completo(self):
        """Diccionario completo incluyendo items y datos completos"""
        data = self.to_dict()
        data['items'] = self.get_items_parsed()
        data['datos_completos'] = self.get_datos_completos_parsed()
        return data
    
    def get_items_parsed(self):
        """Obtener los items de la orden parseados"""
        try:
            return json.loads(self.items_json) if self.items_json else []
        except:
            return []
    
    def get_datos_completos_parsed(self):
        """Obtener los datos completos parseados"""
        try:
            return json.loads(self.datos_completos) if self.datos_completos else {}
        except:
            return {}
    
    def calcular_total_completo(self):
        """Calcular el total completo de la orden"""
        total = 0
        if self.total_order:
            total += float(self.total_order)
        if self.delivery_fee:
            total += float(self.delivery_fee)
        if self.service_fee:
            total += float(self.service_fee)
        if self.tip:
            total += float(self.tip)
        return total
    
    def get_estado_display(self):
        """Obtener el estado en español para mostrar"""
        estados = {
            'pending': 'Pendiente',
            'accepted': 'Aceptada',
            'rejected': 'Rechazada',
            'ready': 'Lista para recoger',
            'delivered': 'Entregada',
            'cancelled': 'Cancelada'
        }
        return estados.get(self.estado, self.estado)
    
    def __repr__(self):
        return f'<RappiOrder {self.order_id}: {self.estado}>'

class ConfiguracionRappi(db.Model):
    """Tabla para configuración de la integración con Rappi"""
    __tablename__ = 'ConfiguracionRappi'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    
    # Configuración de webhooks
    webhook_secret = db.Column(db.String(255))  # Secret para validar webhooks
    webhook_url = db.Column(db.String(500))  # URL donde Rappi envía los webhooks
    
    # Credenciales de Rappi
    store_id = db.Column(db.String(100))
    client_id = db.Column(db.String(255))
    client_secret = db.Column(db.String(255))
    
    # URLs de API
    api_base_url = db.Column(db.String(500), default='https://microservices.dev.rappi.com')
    auth_url = db.Column(db.String(500), default='/restaurants/auth/v1/token/login/integrations')
    
    # Configuración general
    activo = db.Column(db.Boolean, default=True)
    auto_accept_orders = db.Column(db.Boolean, default=False)  # Aceptar órdenes automáticamente
    default_cooking_time = db.Column(db.Integer, default=30)  # Tiempo de cocción por defecto
    
    # Configuración de notificaciones
    email_notifications = db.Column(db.Boolean, default=True)
    email_recipients = db.Column(db.String(500))  # Emails separados por coma
    
    # Metadatos
    fecha_creacion = db.Column(db.DateTime, default=datetime.utcnow)
    fecha_modificacion = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    usuario_modificacion = db.Column(db.String(100))
    
    def to_dict(self):
        return {
            'id': self.id,
            'webhook_secret': self.webhook_secret,
            'webhook_url': self.webhook_url,
            'store_id': self.store_id,
            'client_id': self.client_id,
            'client_secret': '***' if self.client_secret else None,  # Ocultar secret
            'api_base_url': self.api_base_url,
            'auth_url': self.auth_url,
            'activo': self.activo,
            'auto_accept_orders': self.auto_accept_orders,
            'default_cooking_time': self.default_cooking_time,
            'email_notifications': self.email_notifications,
            'email_recipients': self.email_recipients,
            'fecha_creacion': self.fecha_creacion.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_creacion else None,
            'fecha_modificacion': self.fecha_modificacion.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_modificacion else None,
            'usuario_modificacion': self.usuario_modificacion
        }
    
    def to_dict_completo(self):
        """Diccionario completo incluyendo secrets (solo para admin)"""
        data = self.to_dict()
        data['client_secret'] = self.client_secret
        return data
    
    def __repr__(self):
        return f'<ConfiguracionRappi {self.store_id}>'

class Usuario(UserMixin, db.Model):
    """Tabla de usuarios para el sistema de webhooks"""
    __tablename__ = 'Usuarios'
    
    UsuarioID = db.Column(db.Integer, primary_key=True, autoincrement=True)
    Username = db.Column(db.String(50), nullable=False, unique=True)
    Password = db.Column(db.String(255), nullable=False)
    NombreCompleto = db.Column(db.String(200), nullable=False)
    Email = db.Column(db.String(100))
    Activo = db.Column(db.Boolean, nullable=False, default=True)
    FechaCreacion = db.Column(db.DateTime, default=datetime.utcnow)
    UltimoAcceso = db.Column(db.DateTime)
    Rol = db.Column(db.String(50), default='Usuario')
    
    def set_password(self, password):
        """Establecer contraseña con hash"""
        self.Password = generate_password_hash(password)
    
    def check_password(self, password):
        """Verificar contraseña"""
        return check_password_hash(self.Password, password)
    
    def get_id(self):
        """Requerido por Flask-Login"""
        return str(self.UsuarioID)
    
    def to_dict(self):
        return {
            'UsuarioID': self.UsuarioID,
            'Username': self.Username,
            'NombreCompleto': self.NombreCompleto,
            'Email': self.Email,
            'Activo': self.Activo,
            'FechaCreacion': self.FechaCreacion.strftime('%Y-%m-%d %H:%M:%S') if self.FechaCreacion else None,
            'UltimoAcceso': self.UltimoAcceso.strftime('%Y-%m-%d %H:%M:%S') if self.UltimoAcceso else None,
            'Rol': self.Rol
        }
    
    def __repr__(self):
        return f'<Usuario {self.Username}: {self.NombreCompleto}>'

class LogActividad(db.Model):
    """Tabla para registrar actividades del sistema"""
    __tablename__ = 'LogActividad'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    usuario_id = db.Column(db.Integer, db.ForeignKey('Usuarios.UsuarioID'))
    accion = db.Column(db.String(100), nullable=False)  # LOGIN, LOGOUT, UPDATE_CONFIG, etc.
    descripcion = db.Column(db.String(500))
    datos_adicionales = db.Column(db.Text)  # JSON con datos adicionales
    ip_address = db.Column(db.String(45))
    user_agent = db.Column(db.String(500))
    fecha_accion = db.Column(db.DateTime, default=datetime.utcnow)
    
    # Relaciones
    usuario = db.relationship('Usuario', backref='actividades')
    
    def to_dict(self):
        return {
            'id': self.id,
            'usuario_id': self.usuario_id,
            'username': self.usuario.Username if self.usuario else None,
            'accion': self.accion,
            'descripcion': self.descripcion,
            'datos_adicionales': self.datos_adicionales,
            'ip_address': self.ip_address,
            'user_agent': self.user_agent,
            'fecha_accion': self.fecha_accion.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_accion else None
        }
    
    def __repr__(self):
        return f'<LogActividad {self.id}: {self.accion}>'

class EstadisticasRappi(db.Model):
    """Tabla para almacenar estadísticas diarias"""
    __tablename__ = 'EstadisticasRappi'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    fecha = db.Column(db.Date, nullable=False)
    
    # Estadísticas de órdenes
    ordenes_recibidas = db.Column(db.Integer, default=0)
    ordenes_aceptadas = db.Column(db.Integer, default=0)
    ordenes_rechazadas = db.Column(db.Integer, default=0)
    ordenes_canceladas = db.Column(db.Integer, default=0)
    ordenes_completadas = db.Column(db.Integer, default=0)
    
    # Estadísticas financieras
    total_ventas = db.Column(db.Numeric(10, 2), default=0)
    total_delivery_fees = db.Column(db.Numeric(10, 2), default=0)
    total_service_fees = db.Column(db.Numeric(10, 2), default=0)
    total_tips = db.Column(db.Numeric(10, 2), default=0)
    
    # Estadísticas de tiempo
    tiempo_promedio_aceptacion = db.Column(db.Integer)  # En minutos
    tiempo_promedio_preparacion = db.Column(db.Integer)  # En minutos
    
    # Metadatos
    fecha_calculo = db.Column(db.DateTime, default=datetime.utcnow)
    
    def to_dict(self):
        return {
            'id': self.id,
            'fecha': self.fecha.strftime('%Y-%m-%d') if self.fecha else None,
            'ordenes_recibidas': self.ordenes_recibidas,
            'ordenes_aceptadas': self.ordenes_aceptadas,
            'ordenes_rechazadas': self.ordenes_rechazadas,
            'ordenes_canceladas': self.ordenes_canceladas,
            'ordenes_completadas': self.ordenes_completadas,
            'total_ventas': float(self.total_ventas) if self.total_ventas else 0,
            'total_delivery_fees': float(self.total_delivery_fees) if self.total_delivery_fees else 0,
            'total_service_fees': float(self.total_service_fees) if self.total_service_fees else 0,
            'total_tips': float(self.total_tips) if self.total_tips else 0,
            'tiempo_promedio_aceptacion': self.tiempo_promedio_aceptacion,
            'tiempo_promedio_preparacion': self.tiempo_promedio_preparacion,
            'fecha_calculo': self.fecha_calculo.strftime('%Y-%m-%d %H:%M:%S') if self.fecha_calculo else None
        }
    
    def __repr__(self):
        return f'<EstadisticasRappi {self.fecha}: {self.ordenes_recibidas} órdenes>'

# Índices para mejorar el rendimiento
db.Index('idx_webhook_events_tipo_fecha', WebhookEvent.evento_tipo, WebhookEvent.fecha_recepcion)
db.Index('idx_rappi_orders_estado_fecha', RappiOrder.estado, RappiOrder.fecha_creacion)
db.Index('idx_rappi_orders_order_id', RappiOrder.order_id)
db.Index('idx_log_actividad_fecha', LogActividad.fecha_accion)
db.Index('idx_estadisticas_fecha', EstadisticasRappi.fecha)