"""Reorder alert engine (Mejora #7).

Generates alerts when stock hits zero or falls below reorder_point/min_stock.
Can auto-suggest purchase orders to restock.

Alert lifecycle:
  1. Detect low/zero stock
  2. Create reorder_alert record (deduplicated per inventory_id)
  3. Notify owner (push notification)
  4. Employee acknowledges or generates PO
  5. When PO is received, alert is auto-resolved
"""

from services.inventory_engine import get_stock, get_stock_bulk
from services.audit import log_action


ALERT_TYPES = {
    'zero': {'severity': 'critical', 'message': 'Sin existencias'},
    'low':  {'severity': 'warning', 'message': 'Stock bajo'},
    'over': {'severity': 'info', 'message': 'Sobre-stock'},
}


def generate_alerts(conn, branch_id=None, auto_notify=True):
    """Scan inventory and create reorder_alerts for items that need attention.

    Deduplicates: won't create a new open alert for the same inventory_id
    if one already exists.

    Args:
        conn: psycopg2 connection
        branch_id: optional branch filter
        auto_notify: if True, sends push notification for new alerts

    Returns:
        dict: {created: int, by_type: {'zero': n, 'low': n, 'over': n}}
    """
    cur = conn.cursor()

    # Get current open alert inventory_ids to avoid duplicates
    cur.execute("""
        SELECT inventory_id, alert_type FROM reorder_alerts
        WHERE status = 'open'
    """)
    existing = {(r[0], r[1]) for r in cur.fetchall()}

    # Build inventory query
    where = "WHERE i.is_active = true"
    params = []
    if branch_id:
        where += " AND i.branch_id = %s"
        params.append(branch_id)

    cur.execute(f"""
        SELECT i.id, i.part_number, i.name, i.min_stock, i.max_stock,
               i.reorder_point, i.reorder_qty, i.branch_id
        FROM inventory i {where}
    """, params)
    inv_rows = cur.fetchall()

    # Batch stock lookup
    stock_map = get_stock_bulk(conn, branch_id)

    created = 0
    by_type = {'zero': 0, 'low': 0, 'over': 0}
    new_alerts = []

    for row in inv_rows:
        inv_id, part_num, name, min_s, max_s, reorder_pt, reorder_qty, br_id = row
        stock = stock_map.get(inv_id, 0)

        alert_type = None
        threshold = None
        if stock <= 0:
            alert_type = 'zero'
            threshold = 0
        elif reorder_pt is not None and stock <= reorder_pt:
            alert_type = 'low'
            threshold = reorder_pt
        elif min_s and stock < min_s:
            alert_type = 'low'
            threshold = min_s
        elif max_s and stock > max_s:
            alert_type = 'over'
            threshold = max_s

        if alert_type and (inv_id, alert_type) not in existing:
            cur.execute("""
                INSERT INTO reorder_alerts
                    (inventory_id, branch_id, alert_type, stock_at_alert, threshold, status)
                VALUES (%s, %s, %s, %s, %s, 'open')
            """, (inv_id, br_id, alert_type, stock, threshold))
            created += 1
            by_type[alert_type] += 1
            new_alerts.append({
                'inventory_id': inv_id,
                'part_number': part_num,
                'name': name,
                'type': alert_type,
                'stock': stock,
            })

    cur.close()

    # Push notifications (best-effort)
    if auto_notify and new_alerts:
        try:
            from services.push_service import notify_owner
            for alert in new_alerts[:5]:  # limit to first 5 to avoid spam
                notify_owner(
                    conn,
                    f"Alerta: {ALERT_TYPES[alert['type']]['message']}",
                    f"{alert['name'] or alert['part_number']} — Stock: {alert['stock']}",
                    '/inventory'
                )
        except Exception:
            pass

    return {'created': created, 'by_type': by_type}


def list_alerts(conn, status=None, branch_id=None, limit=50, offset=0):
    """List reorder alerts with inventory details."""
    cur = conn.cursor()
    filters = []
    params = []
    if status:
        filters.append("ra.status = %s")
        params.append(status)
    if branch_id:
        filters.append("ra.branch_id = %s")
        params.append(branch_id)
    where = "WHERE " + " AND ".join(filters) if filters else ""

    cur.execute(f"""
        SELECT ra.id, ra.inventory_id, i.part_number, i.name,
               ra.alert_type, ra.stock_at_alert, ra.threshold, ra.status,
               ra.created_at, ra.resolved_at, b.name as branch_name
        FROM reorder_alerts ra
        JOIN inventory i ON ra.inventory_id = i.id
        LEFT JOIN branches b ON ra.branch_id = b.id
        {where}
        ORDER BY
            CASE ra.alert_type WHEN 'zero' THEN 0 WHEN 'low' THEN 1 ELSE 2 END,
            ra.created_at DESC
        LIMIT %s OFFSET %s
    """, params + [limit, offset])
    rows = cur.fetchall()
    cur.close()
    return [{
        'id': r[0], 'inventory_id': r[1], 'part_number': r[2], 'name': r[3],
        'alert_type': r[4], 'stock_at_alert': r[5], 'threshold': r[6],
        'status': r[7], 'created_at': str(r[8]),
        'resolved_at': str(r[9]) if r[9] else None,
        'branch_name': r[10],
    } for r in rows]


def acknowledge_alert(conn, alert_id, employee_id=None, notes=None):
    """Mark an alert as acknowledged."""
    cur = conn.cursor()
    cur.execute("""
        UPDATE reorder_alerts
        SET status = 'acknowledged', employee_id = %s, notes = COALESCE(notes || ' | ', '') || %s
        WHERE id = %s AND status = 'open'
    """, (employee_id, notes or 'Revisado', alert_id))
    updated = cur.rowcount > 0
    cur.close()
    return updated


def resolve_alert(conn, alert_id, po_id=None, notes=None):
    """Resolve an alert (e.g., when PO is received)."""
    cur = conn.cursor()
    cur.execute("""
        UPDATE reorder_alerts
        SET status = 'resolved', po_id = COALESCE(%s, po_id),
            notes = COALESCE(notes || ' | ', '') || %s,
            resolved_at = NOW()
        WHERE id = %s
    """, (po_id, notes or 'Resuelto', alert_id))
    updated = cur.rowcount > 0
    cur.close()
    return updated


def suggest_po_from_alerts(conn, supplier_id=None, branch_id=None):
    """Generate a suggested PO based on open low/zero stock alerts.

    Returns a dict ready to be passed to supplier_engine.create_po().
    """
    cur = conn.cursor()
    where = "WHERE ra.status = 'open' AND ra.alert_type IN ('zero', 'low')"
    params = []
    if branch_id:
        where += " AND ra.branch_id = %s"
        params.append(branch_id)

    cur.execute(f"""
        SELECT ra.inventory_id, i.part_number, i.name,
               i.reorder_qty, i.min_stock, ra.stock_at_alert
        FROM reorder_alerts ra
        JOIN inventory i ON ra.inventory_id = i.id
        {where}
        ORDER BY i.name
    """, params)
    rows = cur.fetchall()
    cur.close()

    items = []
    for r in rows:
        inv_id, part_num, name, reorder_qty, min_stock, stock = r
        # Suggested qty: reorder_qty if set, otherwise min_stock * 2 - stock
        suggested = reorder_qty if reorder_qty else max((min_stock or 1) * 2 - (stock or 0), 1)
        items.append({
            'inventory_id': inv_id,
            'part_number': part_num,
            'name': name,
            'quantity': suggested,
            'unit_price': 0,  # employee must fill in
        })

    return {
        'supplier_id': supplier_id,
        'items': items,
        'notes': 'Orden sugerida automaticamente desde alertas de reorden',
    }
