from decimal import Decimal
from datetime import datetime, timedelta
from flask import Blueprint, jsonify, request
from sqlalchemy import func
from app.models import db, Factura, FacturaDetalle, Sucursal, Producto, Cliente, Usuario
from app.api.decorators.auth import token_required
from app.api.decorators.rbac import require_role

bp = Blueprint('reports', __name__, url_prefix='/api')

def is_company_admin(user):
    """Check if user is company admin."""
    if user.is_superadmin:
        return True
    return any(acc.rol.nombre in ('Administrador', 'Admin') for acc in user.accesos)

@bp.route('/auditoria', methods=['GET'])
@token_required
def get_auditoria_data(current_user):
    """Get audit trail data."""
    try:
        # Get user's branches
        if is_company_admin(current_user):
            sucursales_ids = [s.id for s in Sucursal.query.filter_by(empresa_id=current_user.empresa_id).all()]
        else:
            sucursales_ids = [acc.sucursal_id for acc in current_user.accesos]

        if not sucursales_ids:
            return jsonify({'comprobantes': [], 'movimientos': [], 'ventas': []}), 200

        # Get filters
        desde = request.args.get('desde', '')
        hasta = request.args.get('hasta', '')
        vendedor_id = request.args.get('vendedor_id', 'todos')
        medio_pago = request.args.get('medio_pago', 'todos')
        q = request.args.get('q', '').lower()

        # Build query with proper relationships
        query = Factura.query.filter(Factura.sucursal_id.in_(sucursales_ids))

        # Date filters
        if desde:
            try:
                desde_dt = datetime.fromisoformat(desde)
                query = query.filter(Factura.fecha_emision >= desde_dt)
            except:
                pass

        if hasta:
            try:
                hasta_dt = datetime.fromisoformat(hasta)
                hasta_dt = hasta_dt.replace(hour=23, minute=59, second=59)
                query = query.filter(Factura.fecha_emision <= hasta_dt)
            except:
                pass

        # Vendor filter
        if vendedor_id != 'todos':
            query = query.filter(Factura.usuario_id == vendedor_id)

        # Payment method filter
        if medio_pago != 'todos':
            query = query.filter(Factura.medio_pago == medio_pago)

        # Search
        if q:
            query = query.filter(
                db.or_(
                    Factura.numero_consecutivo.ilike(f"%{q}%"),
                    Factura.clave.ilike(f"%{q}%"),
                    Cliente.nombre.ilike(f"%{q}%")
                )
            )

        facturas = query.order_by(Factura.fecha_emision.desc()).limit(100).all()

        # Format response
        comprobantes = []
        for f in facturas:
            comprobantes.append({
                'id': str(f.id),
                'fecha': f.fecha_emision.isoformat() if f.fecha_emision else '',
                'consecutivo': f.numero_consecutivo or '',
                'clave': f.clave or '',
                'receptor': f.cliente.nombre if f.cliente else 'Consumidor Final',
                'vendedor': f.usuario.nombre if f.usuario else 'Sistema',
                'monto': float(f.total or 0),
                'medio_pago': f.medio_pago or 'N/A',
                'estado': f.estado or 'Pendiente',
                'has_pdf': bool(f.pdf_comprobante),
                'has_xml': bool(f.xml_comprobante)
            })

        return jsonify({
            'comprobantes': comprobantes,
            'movimientos': [],
            'ventas': comprobantes[:50]
        }), 200

    except Exception as e:
        print(f"Error /api/auditoria: {str(e)}")
        import traceback
        traceback.print_exc()
        return jsonify({'error': str(e), 'comprobantes': [], 'movimientos': [], 'ventas': []}), 500

@bp.route('/reportes', methods=['GET'])
@token_required
def get_reportes_summary(current_user):
    """Get reports summary."""
    try:
        # Get user's branches
        if is_company_admin(current_user):
            sucursales_ids = [s.id for s in Sucursal.query.filter_by(empresa_id=current_user.empresa_id).all()]
        else:
            sucursales_ids = [acc.sucursal_id for acc in current_user.accesos]

        if not sucursales_ids:
            return jsonify({
                'kpis': {'ventas': 0, 'compras': 0, 'utilidad': 0, 'impuestos': 0, 'sku_total': 0, 'valor_inventario': 0, 'stock_bajo': 0},
                'graficos': {'tendencia': [], 'top_productos': []},
                'tablas': {'ventas': [], 'compras': [], 'inventario': [], 'comprobantes': [], 'cotizaciones': []}
            }), 200

        # Get filters
        desde = request.args.get('desde', '')
        hasta = request.args.get('hasta', '')

        # Build query
        query = Factura.query.filter(Factura.sucursal_id.in_(sucursales_ids), Factura.is_draft == False)

        # Date filters
        if desde:
            try:
                desde_dt = datetime.fromisoformat(desde)
                query = query.filter(Factura.fecha_emision >= desde_dt)
            except:
                pass

        if hasta:
            try:
                hasta_dt = datetime.fromisoformat(hasta)
                hasta_dt = hasta_dt.replace(hour=23, minute=59, second=59)
                query = query.filter(Factura.fecha_emision <= hasta_dt)
            except:
                pass

        facturas = query.all()

        # Calculate KPIs
        ventas_brutas = float(sum(f.total or 0 for f in facturas if not f.is_quotation))
        impuestos = float(sum(f.impuestos or 0 for f in facturas if not f.is_quotation))
        utilidad = ventas_brutas * 0.3  # Estimate
        compras = ventas_brutas * 0.4  # Estimate

        # Build charts
        tendencia_dict = {}
        for f in facturas:
            if f.is_quotation or not f.fecha_emision:
                continue
            fecha_str = f.fecha_emision.strftime('%Y-%m-%d')
            tendencia_dict[fecha_str] = tendencia_dict.get(fecha_str, 0) + float(f.total or 0)

        tendencia = [{'label': k, 'valor': float(v)} for k, v in sorted(tendencia_dict.items())]

        # Top products
        top_productos = []
        try:
            top_prod_raw = db.session.query(
                FacturaDetalle.descripcion,
                func.sum(FacturaDetalle.total_linea).label('total')
            ).join(Factura).filter(Factura.sucursal_id.in_(sucursales_ids))
            
            if desde:
                try:
                    desde_dt = datetime.fromisoformat(desde)
                    top_prod_raw = top_prod_raw.filter(Factura.fecha_emision >= desde_dt)
                except:
                    pass
            
            if hasta:
                try:
                    hasta_dt = datetime.fromisoformat(hasta)
                    top_prod_raw = top_prod_raw.filter(Factura.fecha_emision <= hasta_dt)
                except:
                    pass
            
            top_prod = top_prod_raw.group_by(FacturaDetalle.descripcion).order_by(db.desc('total')).limit(5).all()
            top_productos = [{'label': str(p.descripcion or 'Producto'), 'valor': float(p.total or 0)} for p in top_prod]
        except:
            pass

        # Inventory
        productos = Producto.query.filter_by(empresa_id=current_user.empresa_id).all()
        inventario = [{
            'codigo': str(p.codigo or 'N/A'),
            'descripcion': str(p.descripcion or 'Sin nombre'),
            'categoria': str(p.marca or 'General'),
            'precio_compra': float(p.costo or 0),
            'precio_venta': float(p.precio_venta or 0),
            'existencia': int(p.stock or 0),
            'status': 'Bajo' if (p.stock or 0) <= 5 else 'OK'
        } for p in productos]

        valor_inventario = sum(p.stock * p.costo for p in productos if p.costo)

        # Format tables
        ventas_table = [{
            'fecha': f.fecha_emision.isoformat() if f.fecha_emision else '',
            'numero': f.numero_consecutivo or '',
            'cliente': f.cliente.nombre if f.cliente else 'Consumidor Final',
            'bruto': float(f.subtotal or 0),
            'impuestos': float(f.impuestos or 0),
            'total': float(f.total or 0),
            'estado': f.estado or 'Pendiente'
        } for f in facturas if not f.is_quotation]

        comprobantes_table = [{
            'consecutivo': f.numero_consecutivo or '',
            'fecha': f.fecha_emision.isoformat() if f.fecha_emision else '',
            'receptor': f.cliente.nombre if f.cliente else 'Consumidor Final',
            'estado': f.estado or 'Pendiente',
            'clave': f.clave or ''
        } for f in facturas if f.xml_comprobante]

        cotizaciones_table = [{
            'fecha': f.fecha_emision.isoformat() if f.fecha_emision else '',
            'numero': f.numero_consecutivo or '',
            'cliente': f.cliente.nombre if f.cliente else 'Consumidor Final',
            'vencimiento': f.fecha_vencimiento.isoformat() if f.fecha_vencimiento else '',
            'total': float(f.total or 0),
            'estado': f.estado or 'Pendiente'
        } for f in facturas if f.is_quotation]

        return jsonify({
            'kpis': {
                'ventas': ventas_brutas,
                'compras': compras,
                'utilidad': utilidad,
                'impuestos': impuestos,
                'sku_total': len(productos),
                'valor_inventario': float(valor_inventario or 0),
                'stock_bajo': len([p for p in productos if (p.stock or 0) <= 5])
            },
            'graficos': {
                'tendencia': tendencia,
                'top_productos': top_productos
            },
            'tablas': {
                'ventas': ventas_table,
                'compras': [],
                'inventario': inventario,
                'comprobantes': comprobantes_table,
                'cotizaciones': cotizaciones_table
            }
        }), 200

    except Exception as e:
        print(f"Error /api/reportes: {str(e)}")
        import traceback
        traceback.print_exc()
        return jsonify({
            'error': str(e),
            'kpis': {'ventas': 0, 'compras': 0, 'utilidad': 0, 'impuestos': 0, 'sku_total': 0, 'valor_inventario': 0, 'stock_bajo': 0},
            'graficos': {'tendencia': [], 'top_productos': []},
            'tablas': {'ventas': [], 'compras': [], 'inventario': [], 'comprobantes': [], 'cotizaciones': []}
        }), 500
