"""Savings Engine: calculate and track how much customers save vs retail price.

Provides:
- Calculate savings per item at checkout
- Update customer total savings
- Generate savings reports
"""

from decimal import Decimal, ROUND_HALF_UP


def calculate_item_savings(unit_price, retail_price, quantity=1):
    """Calculate savings for a single item.

    Returns:
        savings_amount (float), savings_pct (float)
    """
    if not retail_price or retail_price <= 0:
        return 0.0, 0.0
    if not unit_price or unit_price <= 0:
        return 0.0, 0.0

    savings = (Decimal(str(retail_price)) - Decimal(str(unit_price))) * Decimal(str(quantity))
    savings = savings.quantize(Decimal('0.01'), ROUND_HALF_UP)

    pct = (savings / (Decimal(str(retail_price)) * Decimal(str(quantity)))) * 100
    pct = float(pct.quantize(Decimal('0.1'), ROUND_HALF_UP))

    return float(savings), pct


def record_sale_savings(conn, sale_id):
    """Recalculate and record savings for all items in a sale.

    Called after sale is created. Updates sale_items.savings_amount and sales.total_savings.
    Also updates customers.total_savings.
    """
    cur = conn.cursor()

    # Get all items with their retail prices
    cur.execute("""
        SELECT si.id, si.inventory_id, si.unit_price, si.quantity, i.retail_price
        FROM sale_items si
        LEFT JOIN inventory i ON si.inventory_id = i.id
        WHERE si.sale_id = %s
    """, (sale_id,))

    total_savings = Decimal('0')
    for row in cur.fetchall():
        item_id, inv_id, unit_price, qty, retail_price = row
        savings, _ = calculate_item_savings(unit_price, retail_price, qty)
        if savings > 0:
            cur.execute("""
                UPDATE sale_items SET savings_amount = %s WHERE id = %s
            """, (savings, item_id))
            total_savings += Decimal(str(savings))

    # Update sale total savings
    cur.execute("""
        UPDATE sales SET total_savings = %s WHERE id = %s
    """, (total_savings, sale_id))

    # Update customer total savings
    cur.execute("""
        UPDATE customers
        SET total_savings = COALESCE(total_savings, 0) + %s
        WHERE id = (SELECT customer_id FROM sales WHERE id = %s)
    """, (total_savings, sale_id))

    conn.commit()
    cur.close()
    return float(total_savings)


def get_customer_savings_report(conn, customer_id, months=12):
    """Get savings report for a customer."""
    cur = conn.cursor()

    # Overall savings
    cur.execute("""
        SELECT COALESCE(SUM(total_savings), 0), COUNT(*)
        FROM sales
        WHERE customer_id = %s AND status = 'completed' AND total_savings > 0
    """, (customer_id,))
    total_saved, orders_with_savings = cur.fetchone()

    # Monthly breakdown
    cur.execute("""
        SELECT
            date_trunc('month', created_at) as month,
            COUNT(*) as orders,
            SUM(total) as spent,
            SUM(total_savings) as saved
        FROM sales
        WHERE customer_id = %s AND status = 'completed' AND total_savings > 0
          AND created_at >= NOW() - interval '%s months'
        GROUP BY date_trunc('month', created_at)
        ORDER BY month DESC
    """, (customer_id, months))

    monthly = []
    for r in cur.fetchall():
        monthly.append({
            'month': str(r[0])[:7],
            'orders': r[1],
            'spent': float(r[2]) if r[2] else 0,
            'saved': float(r[3]) if r[3] else 0,
            'savings_pct': round(float(r[3]) / float(r[2]) * 100, 1) if r[2] else 0,
        })

    # Top savings items
    cur.execute("""
        SELECT si.name, si.part_number, si.unit_price, si.retail_price, si.savings_amount
        FROM sale_items si
        JOIN sales s ON s.id = si.sale_id
        WHERE s.customer_id = %s AND s.status = 'completed' AND si.savings_amount > 0
        ORDER BY si.savings_amount DESC
        LIMIT 10
    """, (customer_id,))

    top_items = []
    for r in cur.fetchall():
        top_items.append({
            'name': r[0], 'part_number': r[1],
            'unit_price': float(r[2]) if r[2] else 0,
            'retail_price': float(r[3]) if r[3] else 0,
            'savings': float(r[4]) if r[4] else 0,
        })

    cur.close()

    return {
        'customer_id': customer_id,
        'total_saved': float(total_saved) if total_saved else 0,
        'orders_with_savings': orders_with_savings or 0,
        'monthly_breakdown': monthly,
        'top_items': top_items,
    }


def get_global_savings_stats(conn, tenant_id, from_date=None, to_date=None):
    """Get global savings stats for a tenant."""
    cur = conn.cursor()
    params = [tenant_id]
    date_filter = ""
    if from_date:
        date_filter += " AND s.created_at >= %s"
        params.append(from_date)
    if to_date:
        date_filter += " AND s.created_at < %s::date + interval '1 day'"
        params.append(to_date)

    cur.execute(f"""
        SELECT
            COALESCE(SUM(s.total_savings), 0),
            COUNT(DISTINCT s.customer_id),
            COUNT(*) as orders,
            COALESCE(AVG(s.total_savings), 0)
        FROM sales s
        JOIN customers c ON s.customer_id = c.id
        WHERE s.status = 'completed' AND s.total_savings > 0
          {date_filter}
    """, params[1:] if len(params) > 1 else [])

    total_saved, customers_count, orders, avg_savings = cur.fetchone()

    cur.execute(f"""
        SELECT c.name, c.id, SUM(s.total_savings) as saved
        FROM sales s
        JOIN customers c ON s.customer_id = c.id
        WHERE s.status = 'completed' AND s.total_savings > 0
          {date_filter}
        GROUP BY c.id, c.name
        ORDER BY saved DESC
        LIMIT 10
    """, params[1:] if len(params) > 1 else [])

    top_customers = []
    for r in cur.fetchall():
        top_customers.append({'name': r[0], 'id': r[1], 'saved': float(r[2]) if r[2] else 0})

    cur.close()
    return {
        'total_saved': float(total_saved) if total_saved else 0,
        'customers_count': customers_count or 0,
        'orders_count': orders or 0,
        'avg_savings_per_order': float(avg_savings) if avg_savings else 0,
        'top_customers': top_customers,
    }
