"""Dashboard Stats Blueprint — In-app real-time analytics.

Endpoints for sales, productivity, and top products charts.
"""
from flask import Blueprint, request, jsonify, g
from functools import wraps
from datetime import datetime, timedelta
from decimal import Decimal
import json

dashboard_stats_bp = Blueprint('dashboard_stats', __name__, url_prefix='/pos/api/dashboard')


from middleware import require_auth
from tenant_db import get_tenant_conn


class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, Decimal):
            return float(o)
        return super().default(o)


@dashboard_stats_bp.route('/stats', methods=['GET'])
@require_auth()
def get_stats():
    """Summary stats for today and this month."""
    conn = get_tenant_conn(g.tenant_id)
    cur = conn.cursor()
    today = datetime.utcnow().date()
    month_start = today.replace(day=1)

    try:
        # Sales today
        cur.execute(
            """SELECT COUNT(*) as count, COALESCE(SUM(total), 0) as total
               FROM sales WHERE DATE(created_at) = %s""", (today,)
        )
        today_sales = cur.fetchone()

        # Sales this month
        cur.execute(
            """SELECT COUNT(*) as count, COALESCE(SUM(total), 0) as total
               FROM sales WHERE DATE(created_at) >= %s""", (month_start,)
        )
        month_sales = cur.fetchone()

        # Top 5 products today
        cur.execute(
            """SELECT si.name, SUM(si.quantity) as qty, SUM(si.subtotal) as revenue
               FROM sale_items si
               JOIN sales s ON si.sale_id = s.id
               WHERE DATE(s.created_at) = %s
               GROUP BY si.name
               ORDER BY revenue DESC
               LIMIT 5""", (today,)
        )
        top_products = cur.fetchall()

        # Hourly sales today (0-23)
        cur.execute(
            """SELECT EXTRACT(HOUR FROM created_at)::int as hour,
                      COUNT(*) as count, COALESCE(SUM(total), 0) as total
               FROM sales WHERE DATE(created_at) = %s
               GROUP BY hour ORDER BY hour""", (today,)
        )
        hourly = cur.fetchall()
        hourly_map = {row[0]: {'count': row[1], 'total': row[2]} for row in hourly}

        return jsonify({
            'today': {
                'sales_count': today_sales[0],
                'sales_total': float(today_sales[1]) if today_sales[1] is not None else 0,
            },
            'month': {
                'sales_count': month_sales[0],
                'sales_total': float(month_sales[1]) if month_sales[1] is not None else 0,
            },
            'top_products': [
                {'name': row[0], 'quantity': row[1], 'revenue': float(row[2]) if row[2] is not None else 0}
                for row in top_products
            ],
            'hourly_sales': [
                {'hour': h, 'count': hourly_map.get(h, {}).get('count', 0),
                 'total': float(hourly_map.get(h, {}).get('total', 0))}
                for h in range(24)
            ],
        })
    finally:
        cur.close()
        conn.close()


@dashboard_stats_bp.route('/stats/employees', methods=['GET'])
@require_auth()
def get_employee_stats():
    """Sales per employee today."""
    conn = get_tenant_conn(g.tenant_id)
    cur = conn.cursor()
    today = datetime.utcnow().date()
    try:
        cur.execute(
            """SELECT e.name, COUNT(s.id) as sales, COALESCE(SUM(s.total), 0) as total
               FROM sales s
               JOIN employees e ON s.employee_id = e.id
               WHERE DATE(s.created_at) = %s
               GROUP BY e.name
               ORDER BY total DESC""", (today,)
        )
        rows = cur.fetchall()
        return jsonify({
            'employees': [
                {'name': row[0], 'sales': row[1], 'total': float(row[2]) if row[2] is not None else 0}
                for row in rows
            ]
        })
    finally:
        cur.close()
        conn.close()


@dashboard_stats_bp.route('/credit-alerts', methods=['GET'])
@require_auth()
def credit_alerts():
    """Credit sales that are overdue or due within the next 7 days."""
    conn = get_tenant_conn(g.tenant_id)
    cur = conn.cursor()
    try:
        cur.execute("""
            SELECT s.id,
                   c.name as customer_name,
                   s.total,
                   s.created_at,
                   s.created_at + INTERVAL '30 days' as due_date,
                   COALESCE(SUM(sp.amount), 0) as paid
            FROM sales s
            JOIN customers c ON c.id = s.customer_id
            LEFT JOIN sale_payments sp ON sp.sale_id = s.id
            WHERE s.sale_type = 'credit'
              AND s.status = 'completed'
            GROUP BY s.id, c.name, s.total, s.created_at
            HAVING s.total - COALESCE(SUM(sp.amount), 0) > 0
               AND s.created_at + INTERVAL '30 days' <= NOW() + INTERVAL '30 days'
            ORDER BY due_date
            LIMIT 50
        """)

        rows = []
        now = datetime.utcnow()
        for r in cur.fetchall():
            sale_id = r[0]
            customer_name = r[1]
            total = float(r[2]) if r[2] else 0
            paid = float(r[5]) if r[5] else 0
            balance = round(total - paid, 2)
            created_at = r[3]
            due_date = r[4]
            days_until_due = (due_date.replace(tzinfo=None) - now).days if due_date else None

            if days_until_due is None:
                continue
            status = 'overdue' if days_until_due < 0 else ('due_soon' if days_until_due <= 7 else 'current')
            label = 'Vencida' if status == 'overdue' else ('Por vencer' if status == 'due_soon' else 'Al corriente')

            rows.append({
                'sale_id': sale_id,
                'folio': f'VTA-{sale_id}',
                'customer_name': customer_name,
                'issue_date': created_at.isoformat() if created_at else None,
                'due_date': due_date.isoformat() if due_date else None,
                'days_until_due': days_until_due,
                'total': total,
                'paid': paid,
                'balance': balance,
                'status': status,
                'status_label': label,
            })

        return jsonify({
            'data': rows,
            'overdue_count': sum(1 for r in rows if r['status'] == 'overdue'),
            'due_soon_count': sum(1 for r in rows if r['status'] == 'due_soon'),
        })
    finally:
        cur.close()
        conn.close()
