"""
AI-driven smart suggestions for inventory management
Generates top recommendations based on SKU demand forecasting
"""

import pandas as pd
import numpy as np
from datetime import timedelta
from typing import List, Dict
import warnings
warnings.filterwarnings('ignore')


def get_smart_suggestions(order_items_df: pd.DataFrame, 
                          inventory_df: pd.DataFrame = None, 
                          top_n: int = 3) -> List[Dict]:
    """
    Generate AI-driven inventory recommendations using order_items_df
    
    Args:
        order_items_df: DataFrame with columns [order_id, order_date, sku, qty, price?]
        inventory_df:   Optional DataFrame with current inventory levels
        top_n:          Number of recommendations to return
    
    Returns:
        List of recommendation dictionaries
    """
    recommendations = []

    # Ensure order_date is datetime
    if "order_date" not in order_items_df.columns:
        raise ValueError("order_items_df must contain column 'order_date'")

    order_items_df["order_date"] = pd.to_datetime(order_items_df["order_date"],
                                                  errors="coerce")
    order_items_df = order_items_df.dropna(subset=["order_date"])

    # Get SKU-level aggregated statistics
    sku_stats = analyze_sku_patterns(order_items_df)

    # 1. HIGH DEMAND ALERT - SKUs with increasing demand
    high_demand = identify_high_demand(sku_stats, order_items_df)
    for sku_info in high_demand[:2]:
        recommendations.append({
            "type": "high_demand",
            "priority": "high",
            "sku": sku_info["sku"],
            "message": f"📈 High demand detected for {sku_info['sku'][:20]}...",
            "detail": f"Recent orders up {sku_info['increase']:.0f}% vs prior period. Consider increasing stock.",
            "confidence": sku_info["confidence"]
        })

    # 2. RESTOCK ALERT - SKUs running low based on velocity
    restock = identify_restock_needs(sku_stats, order_items_df)
    for sku_info in restock[:2]:
        recommendations.append({
            "type": "restock",
            "priority": "medium",
            "sku": sku_info["sku"],
            "message": f"⚠️ Restock recommended for {sku_info['sku'][:20]}...",
            "detail": f"Avg {sku_info['avg_daily']:.1f} units/day. "
                      f"Forecast: {sku_info['forecast']:.0f} units next 7 days.",
            "confidence": sku_info["confidence"]
        })

    # 3. SLOW MOVING - declining demand
    slow = identify_slow_moving(sku_stats, order_items_df)
    for sku_info in slow[:1]:
        recommendations.append({
            "type": "slow_moving",
            "priority": "low",
            "sku": sku_info["sku"],
            "message": f"📉 Declining demand for {sku_info['sku'][:20]}...",
            "detail": f"Orders down {sku_info['decline']:.0f}% recently. Consider promotional activities.",
            "confidence": sku_info["confidence"]
        })

    # Sort recommendations by priority
    priority_order = {"high": 0, "medium": 1, "low": 2}
    recommendations.sort(key=lambda x: priority_order[x["priority"]])

    return recommendations[:top_n]


# ----------------------------------------------------------------------
# Helper functions
# ----------------------------------------------------------------------

def analyze_sku_patterns(order_items_df: pd.DataFrame) -> pd.DataFrame:
    """Analyze order patterns for each SKU"""
    sku_stats = order_items_df.groupby("sku").agg({
        "qty": ["sum", "mean", "count"],
        "order_date": ["min", "max"]
    }).reset_index()

    sku_stats.columns = [
        "sku", "total_qty", "avg_qty", "order_count",
        "first_order", "last_order"
    ]

    # Calculate days active (avoid divide-by-zero)
    sku_stats["days_active"] = (
        (sku_stats["last_order"] - sku_stats["first_order"]).dt.days + 1
    ).clip(lower=1)

    sku_stats["avg_daily_qty"] = sku_stats["total_qty"] / sku_stats["days_active"]

    return sku_stats


def identify_high_demand(sku_stats: pd.DataFrame, 
                         order_items_df: pd.DataFrame) -> List[Dict]:
    """Identify SKUs with increasing demand trends"""
    results = []

    cutoff = order_items_df["order_date"].max() - timedelta(days=30)

    for _, row in sku_stats.iterrows():
        sku = row["sku"]
        sku_orders = order_items_df[order_items_df["sku"] == sku]

        if len(sku_orders) < 5:
            continue

        recent = sku_orders[sku_orders["order_date"] > cutoff]["qty"].sum()
        historical = sku_orders[sku_orders["order_date"] <= cutoff]["qty"].sum()

        if historical <= 0:
            continue

        recent_days = (sku_orders["order_date"].max() - cutoff).days
        historical_days = (cutoff - sku_orders["order_date"].min()).days

        if recent_days <= 0 or historical_days <= 0:
            continue

        recent_daily = recent / recent_days
        historical_daily = historical / historical_days

        if historical_daily <= 0:
            continue

        increase = ((recent_daily - historical_daily) / historical_daily) * 100

        if increase > 20:  # threshold
            results.append({
                "sku": sku,
                "increase": increase,
                "confidence": min(95, 70 + (increase / 10))
            })

    return sorted(results, key=lambda x: x["increase"], reverse=True)


def identify_restock_needs(sku_stats: pd.DataFrame, 
                           order_items_df: pd.DataFrame) -> List[Dict]:
    """Identify SKUs that need restocking based on demand velocity"""
    results = []

    # Look at the SKUs with the highest avg daily usage
    for _, row in sku_stats.nlargest(20, "avg_daily_qty").iterrows():
        sku = row["sku"]
        avg_daily = row["avg_daily_qty"]

        forecast_7d = avg_daily * 7

        if avg_daily > 0.5:  # velocity threshold
            results.append({
                "sku": sku,
                "avg_daily": avg_daily,
                "forecast": forecast_7d,
                "confidence": min(90, 60 + (row["order_count"] * 2))
            })

    return sorted(results, key=lambda x: x["forecast"], reverse=True)


def identify_slow_moving(sku_stats: pd.DataFrame, 
                         order_items_df: pd.DataFrame) -> List[Dict]:
    """Identify SKUs with declining demand"""
    results = []
    cutoff = order_items_df["order_date"].max() - timedelta(days=30)

    for _, row in sku_stats.iterrows():
        sku = row["sku"]
        sku_orders = order_items_df[order_items_df["sku"] == sku]

        if len(sku_orders) < 5:
            continue

        recent = sku_orders[sku_orders["order_date"] > cutoff]["qty"].sum()
        historical = sku_orders[sku_orders["order_date"] <= cutoff]["qty"].sum()

        if recent <= 0 or historical <= 0:
            continue

        recent_days = (sku_orders["order_date"].max() - cutoff).days
        historical_days = (cutoff - sku_orders["order_date"].min()).days

        if recent_days <= 0 or historical_days <= 0:
            continue

        recent_daily = recent / recent_days
        historical_daily = historical / historical_days

        if historical_daily <= 0:
            continue

        decline = ((historical_daily - recent_daily) / historical_daily) * 100

        if decline > 30:  # threshold
            results.append({
                "sku": sku,
                "decline": decline,
                "confidence": min(85, 60 + (decline / 5))
            })

    return sorted(results, key=lambda x: x["decline"], reverse=True)
