import json
import traceback
from datetime import datetime
from django.utils import timezone
from django.db.models import Sum
from sales.models import POSOrder
from inventory.models import Product, Supplier, PurchaseOrder, PurchaseOrderItem
from analytics.models import OperatingExpense

def get_stock_report(company):
    """
    Returns a JSON string of stock numbers: low stock, out of stock items, and top 5 items.
    """
    try:
        low_stock = list(Product.objects.filter(company=company, stock_status='low_stock').values('name', 'stock_quantity', 'sku'))
        out_of_stock = list(Product.objects.filter(company=company, stock_status='out_of_stock').values('name', 'sku'))
        
        # Optionally get top quantities
        top_stock = list(Product.objects.filter(company=company).order_by('-stock_quantity').values('name', 'stock_quantity')[:5])
        
        return json.dumps({
            "low_stock_items": low_stock,
            "out_of_stock_items": out_of_stock,
            "highest_stock_items": top_stock
        })
    except Exception as e:
        return json.dumps({"error": str(e)})


def get_financial_summary(company, start_date=None, end_date=None):
    """
    Returns a financial summary (sales, revenue, profit, expenses) for a specific date range.
    start_date and end_date should be 'YYYY-MM-DD' strings. If none, defaults to today.
    """
    try:
        if not start_date:
            start_dt = timezone.now().date()
        else:
            start_dt = datetime.strptime(start_date, '%Y-%m-%d').date()
            
        if not end_date:
            end_dt = start_dt
        else:
            end_dt = datetime.strptime(end_date, '%Y-%m-%d').date()
            
        orders = POSOrder.objects.filter(
            company=company,
            status='completed',
            created_at__date__gte=start_dt,
            created_at__date__lte=end_dt
        )
        
        total_revenue = orders.aggregate(total=Sum('final_amount'))['total'] or 0
        total_tax = orders.aggregate(total=Sum('tax_amount'))['total'] or 0
        
        # Calculate COGS correctly using product cost_price (not selling price)
        from sales.models import POSOrderItem
        cogs = 0
        gross_profit = 0
        items_qs = POSOrderItem.objects.filter(order__in=orders).select_related('product')
        for item in items_qs:
            cost = float(item.product.cost_price or 0) if item.product else 0
            revenue_line = float(item.unit_price) * item.quantity
            cogs_line = cost * item.quantity
            cogs += cogs_line
            gross_profit += revenue_line - cogs_line

        unpaid = orders.filter(balance_amount__gt=0).aggregate(total=Sum('balance_amount'))['total'] or 0
        
        expenses = OperatingExpense.objects.filter(
            company=company,
            expense_date__gte=start_dt,
            expense_date__lte=end_dt
        ).aggregate(total=Sum('amount'))['total'] or 0
        
        net_profit = gross_profit - float(expenses)

        return json.dumps({
            "period": f"{start_dt} to {end_dt}",
            "total_revenue": float(total_revenue),
            "total_tax_collected": float(total_tax),
            "cogs": round(cogs, 2),
            "gross_profit": round(gross_profit, 2),
            "operating_expenses": float(expenses),
            "net_profit": round(net_profit, 2),
            "unpaid_credit_issued": float(unpaid),
            "orders_count": orders.count()
        })
    except Exception as e:
        print(traceback.format_exc())
        return json.dumps({"error": str(e)})


def draft_purchase_order(company, supplier_name, items):
    """
    Drafts a purchase order.
    supplier_name (str): Name of supplier to search for.
    items (list): List of dicts like [{"sku_or_name": "Milk", "quantity": 10}, ...]
    """
    try:
        # Find supplier
        supplier = Supplier.objects.filter(company=company, name__icontains=supplier_name).first()
        if not supplier:
            return json.dumps({"error": f"Supplier containing '{supplier_name}' not found."})
            
        po = PurchaseOrder.objects.create(
            supplier=supplier,
            status="draft",
            reference_number=f"PO-AI-{timezone.now().strftime('%M%S')}"
        )
        
        added_items = []
        missing_items = []
        
        # Parse items securely (in case AI sends string instead of dict)
        if isinstance(items, str):
            try:
                items = json.loads(items)
            except:
                items = []
                
        for item in items:
            search_term = item.get('sku_or_name', '')
            qty = int(item.get('quantity', 1))
            
            prod = Product.objects.filter(company=company, name__icontains=search_term).first()
            if not prod:
                prod = Product.objects.filter(company=company, sku__icontains=search_term).first()
                
            if prod:
                PurchaseOrderItem.objects.create(
                    purchase_order=po,
                    product=prod,
                    quantity=qty,
                    unit_cost=prod.cost_price or 0
                )
                added_items.append(prod.name)
            else:
                missing_items.append(search_term)
                
        if not added_items:
            po.delete()
            return json.dumps({"error": "Failed to match any products for the PO. Please check the product names."})
            
        return json.dumps({
            "success": True,
            "message": f"Drafted Purchase Order #{po.reference_number} for {supplier.name}.",
            "purchase_order_id": po.id,
            "added_products": added_items,
            "not_found_products": missing_items,
            "link": f"/inventory/purchase-orders/{po.id}/"
        })
    except Exception as e:
        return json.dumps({"error": str(e)})
