#!/usr/bin/env python3
"""
Standalone Nemlig.com grocery shopping CLI.

This script provides a simple interface to:
- Parse recipes from URLs
- Search for products on Nemlig.com
- Add ingredients to your cart
- Manage pantry items
- View delivery slots

Usage:
    python nemlig.py login
    python nemlig.py search "mælk"
    python nemlig.py parse "https://valdemarsro.dk/recipe"
    python nemlig.py add "https://valdemarsro.dk/recipe" --servings 4
    python nemlig.py cart
    python nemlig.py pantry list
    python nemlig.py slots

Requirements:
    pip install requests recipe-scrapers httpx beautifulsoup4 python-dotenv
"""

import argparse
import json
import sys
from pathlib import Path

# Add the nemlig_shopper package to the path
script_dir = Path(__file__).parent
sys.path.insert(0, str(script_dir))

from nemlig_shopper.api import NemligAPI, NemligAPIError
from nemlig_shopper.config import get_credentials, save_credentials, clear_credentials, PANTRY_FILE
from nemlig_shopper.recipe_parser import parse_recipe_url, parse_ingredients_text, Recipe
from nemlig_shopper.scaler import scale_recipe
from nemlig_shopper.matcher import match_ingredients, prepare_cart_items, calculate_total_cost
from nemlig_shopper.pantry import load_pantry, add_to_pantry, remove_from_pantry, clear_pantry
from nemlig_shopper.planner import consolidate_ingredients


def cmd_login(args):
    """Login to Nemlig.com."""
    import getpass

    username = args.username or input("Email: ")
    password = args.password or getpass.getpass("Password: ")

    api = NemligAPI()
    try:
        if api.login(username, password):
            save_credentials(username, password)
            print("✓ Login successful! Credentials saved.")
            return 0
    except NemligAPIError as e:
        print(f"✗ Login failed: {e}")
        return 1


def cmd_logout(args):
    """Clear saved credentials."""
    clear_credentials()
    print("✓ Credentials cleared.")
    return 0


def cmd_search(args):
    """Search for products."""
    api = NemligAPI()
    username, password = get_credentials()

    if username and password:
        try:
            api.login(username, password)
        except NemligAPIError:
            pass  # Continue without login

    products = api.search_products(args.query, limit=args.limit)

    if not products:
        print(f"No products found for '{args.query}'")
        return 1

    print(f"\nFound {len(products)} products for '{args.query}':\n")
    for i, p in enumerate(products, 1):
        available = "✓" if p.get("available", True) else "✗"
        print(f"{i}. [{available}] {p['name']} - {p['price']} kr ({p.get('unit_size', '')})")
        print(f"   ID: {p['id']} | Category: {p.get('category', 'N/A')}")

    return 0


def cmd_parse(args):
    """Parse a recipe from URL."""
    try:
        recipe = parse_recipe_url(args.url)
    except Exception as e:
        print(f"✗ Failed to parse recipe: {e}")
        return 1

    print(f"\n📖 {recipe.title}")
    if recipe.servings:
        print(f"   Servings: {recipe.servings}")
    print(f"\nIngredients ({len(recipe.ingredients)}):")

    for ing in recipe.ingredients:
        qty = f"{ing.quantity} " if ing.quantity else ""
        unit = f"{ing.unit} " if ing.unit else ""
        notes = f" ({ing.notes})" if ing.notes else ""
        print(f"  • {qty}{unit}{ing.name}{notes}")

    return 0


def cmd_add(args):
    """Add recipe ingredients to cart."""
    # Parse recipe(s)
    recipes = []
    for url in args.urls:
        try:
            recipe = parse_recipe_url(url)
            recipes.append(recipe)
            print(f"✓ Parsed: {recipe.title}")
        except Exception as e:
            print(f"✗ Failed to parse {url}: {e}")
            if not args.continue_on_error:
                return 1

    if not recipes:
        print("No recipes to process.")
        return 1

    # Scale and consolidate ingredients
    all_scaled = []
    for recipe in recipes:
        scaled, _, _ = scale_recipe(
            recipe,
            target_servings=args.servings,
            multiplier=args.scale
        )
        all_scaled.extend(scaled)

    # Consolidate if multiple recipes
    if len(recipes) > 1:
        consolidated = consolidate_ingredients(all_scaled)
    else:
        from nemlig_shopper.planner import ConsolidatedIngredient
        consolidated = [
            ConsolidatedIngredient(
                name=s.name,
                total_quantity=s.scaled_quantity,
                unit=s.unit,
                sources=[(recipes[0].title, s.original)]
            )
            for s in all_scaled
        ]

    # Filter pantry items
    if not args.skip_pantry:
        pantry_items = load_pantry(PANTRY_FILE)
        from nemlig_shopper.pantry import identify_pantry_items
        pantry_candidates, consolidated = identify_pantry_items(consolidated, pantry_items)
        if pantry_candidates:
            print(f"\n🏠 Skipping {len(pantry_candidates)} pantry items: {', '.join(c.name for c in pantry_candidates)}")

    # Login
    api = NemligAPI()
    username, password = get_credentials()
    if not username or not password:
        print("✗ Not logged in. Run 'python nemlig.py login' first.")
        return 1

    try:
        api.login(username, password)
    except NemligAPIError as e:
        print(f"✗ Login failed: {e}")
        return 1

    # Build dietary options
    allergies = []
    dietary = []
    if args.lactose_free:
        allergies.append("lactose")
    if args.gluten_free:
        allergies.append("gluten")
    if args.vegan:
        dietary.append("vegan")

    # Match ingredients to products
    print(f"\n🔍 Matching {len(consolidated)} ingredients...")

    # Convert consolidated to scaled ingredients format
    from nemlig_shopper.scaler import ScaledIngredient
    from nemlig_shopper.recipe_parser import Ingredient

    scaled_for_matching = [
        ScaledIngredient(
            original=Ingredient(original=c.name, name=c.name, quantity=c.total_quantity, unit=c.unit),
            scaled_quantity=c.total_quantity,
            scale_factor=1.0
        )
        for c in consolidated
    ]

    matches = match_ingredients(
        api,
        scaled_for_matching,
        prefer_organic=args.organic,
        prefer_budget=args.budget,
        allergies=allergies if allergies else None,
        dietary=dietary if dietary else None,
    )

    # Display matches
    print(f"\n🛒 Product matches:\n")
    for match in matches:
        if match.matched:
            status = "✓"
            if not match.is_dietary_safe:
                status = "⚠️"
            print(f"  {status} {match.ingredient_name} → {match.product_name} (x{match.quantity}) - {match.price} kr")
            if match.dietary_warnings:
                for warning in match.dietary_warnings:
                    print(f"      ⚠️ {warning}")
        else:
            print(f"  ✗ {match.ingredient_name} → No match found")

    total = calculate_total_cost(matches)
    print(f"\n💰 Estimated total: {total:.2f} kr")

    if args.dry_run:
        print("\n[Dry run - not adding to cart]")
        return 0

    # Add to cart
    cart_items = prepare_cart_items(matches)
    if not cart_items:
        print("\nNo items to add to cart.")
        return 0

    print(f"\n🛒 Adding {len(cart_items)} items to cart...")
    result = api.add_multiple_to_cart(cart_items)

    success_count = len(result["success"])
    fail_count = len(result["failed"])

    print(f"✓ Added {success_count} items to cart")
    if fail_count:
        print(f"✗ Failed to add {fail_count} items")

    return 0


def cmd_cart(args):
    """View cart contents."""
    api = NemligAPI()
    username, password = get_credentials()

    if not username or not password:
        print("✗ Not logged in. Run 'python nemlig.py login' first.")
        return 1

    try:
        api.login(username, password)
        cart = api.get_cart()
    except NemligAPIError as e:
        print(f"✗ Failed to get cart: {e}")
        return 1

    lines = cart.get("Lines", [])
    if not lines:
        print("🛒 Cart is empty")
        return 0

    print("\n🛒 Cart contents:\n")
    total = 0
    for line in lines:
        name = line.get("ProductName", "Unknown")
        qty = line.get("Quantity", 1)
        price = line.get("Total", 0)
        total += price
        print(f"  • {name} x{qty} - {price:.2f} kr")

    print(f"\n💰 Total: {total:.2f} kr")
    return 0


def cmd_pantry(args):
    """Manage pantry items."""
    if args.pantry_action == "list":
        items = load_pantry(PANTRY_FILE)
        if items:
            print("🏠 Pantry items:")
            for item in sorted(items):
                print(f"  • {item}")
        else:
            print("Pantry is empty.")

    elif args.pantry_action == "add":
        if not args.items:
            print("Specify items to add.")
            return 1
        add_to_pantry(args.items, PANTRY_FILE)
        print(f"✓ Added {len(args.items)} items to pantry.")

    elif args.pantry_action == "remove":
        if not args.items:
            print("Specify items to remove.")
            return 1
        remove_from_pantry(args.items, PANTRY_FILE)
        print(f"✓ Removed {len(args.items)} items from pantry.")

    elif args.pantry_action == "clear":
        clear_pantry(PANTRY_FILE)
        print("✓ Pantry reset to defaults.")

    return 0


def cmd_slots(args):
    """View available delivery slots."""
    api = NemligAPI()
    username, password = get_credentials()

    if not username or not password:
        print("✗ Not logged in. Run 'python nemlig.py login' first.")
        return 1

    try:
        api.login(username, password)
        slots = api.get_delivery_slots(days=args.days)
    except NemligAPIError as e:
        print(f"✗ Failed to get slots: {e}")
        return 1

    if not slots:
        print("No delivery slots available.")
        return 0

    print("\n📅 Available delivery slots:\n")
    current_date = None

    for slot in slots:
        date = slot.get("date", "")[:10]
        if date != current_date:
            current_date = date
            print(f"\n{date}:")

        start = slot.get("start_hour", "")
        end = slot.get("end_hour", "")
        price = slot.get("delivery_price", 0)
        available = "✓" if slot.get("is_available") else "✗"
        slot_id = slot.get("id")

        print(f"  {available} {start}-{end} - {price} kr (ID: {slot_id})")

    return 0


def cmd_select_slot(args):
    """Select a delivery slot."""
    api = NemligAPI()
    username, password = get_credentials()

    if not username or not password:
        print("✗ Not logged in. Run 'python nemlig.py login' first.")
        return 1

    try:
        api.login(username, password)
        result = api.select_delivery_slot(args.slot_id)
    except (NemligAPIError, ValueError) as e:
        print(f"✗ Failed to select slot: {e}")
        return 1

    if result.get("is_reserved"):
        print(f"✓ Slot reserved for {result.get('minutes_reserved', 0)} minutes")
    else:
        print("✗ Failed to reserve slot")
        return 1

    return 0


def main():
    parser = argparse.ArgumentParser(
        description="Nemlig.com grocery shopping CLI",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    subparsers = parser.add_subparsers(dest="command", help="Commands")

    # Login
    login_parser = subparsers.add_parser("login", help="Login to Nemlig.com")
    login_parser.add_argument("--username", "-u", help="Email address")
    login_parser.add_argument("--password", "-p", help="Password")
    login_parser.set_defaults(func=cmd_login)

    # Logout
    logout_parser = subparsers.add_parser("logout", help="Clear saved credentials")
    logout_parser.set_defaults(func=cmd_logout)

    # Search
    search_parser = subparsers.add_parser("search", help="Search for products")
    search_parser.add_argument("query", help="Search query")
    search_parser.add_argument("--limit", "-l", type=int, default=10, help="Max results")
    search_parser.set_defaults(func=cmd_search)

    # Parse
    parse_parser = subparsers.add_parser("parse", help="Parse a recipe from URL")
    parse_parser.add_argument("url", help="Recipe URL")
    parse_parser.set_defaults(func=cmd_parse)

    # Add
    add_parser = subparsers.add_parser("add", help="Add recipe ingredients to cart")
    add_parser.add_argument("urls", nargs="+", help="Recipe URL(s)")
    add_parser.add_argument("--servings", "-s", type=int, help="Target servings")
    add_parser.add_argument("--scale", type=float, help="Scale multiplier")
    add_parser.add_argument("--organic", action="store_true", help="Prefer organic")
    add_parser.add_argument("--budget", action="store_true", help="Prefer cheapest")
    add_parser.add_argument("--lactose-free", action="store_true", help="Lactose-free products")
    add_parser.add_argument("--gluten-free", action="store_true", help="Gluten-free products")
    add_parser.add_argument("--vegan", action="store_true", help="Vegan products")
    add_parser.add_argument("--skip-pantry", action="store_true", help="Don't skip pantry items")
    add_parser.add_argument("--dry-run", action="store_true", help="Preview without adding")
    add_parser.add_argument("--continue-on-error", action="store_true", help="Continue if a recipe fails")
    add_parser.set_defaults(func=cmd_add)

    # Cart
    cart_parser = subparsers.add_parser("cart", help="View cart contents")
    cart_parser.set_defaults(func=cmd_cart)

    # Pantry
    pantry_parser = subparsers.add_parser("pantry", help="Manage pantry items")
    pantry_parser.add_argument("pantry_action", choices=["list", "add", "remove", "clear"])
    pantry_parser.add_argument("items", nargs="*", help="Items to add/remove")
    pantry_parser.set_defaults(func=cmd_pantry)

    # Slots
    slots_parser = subparsers.add_parser("slots", help="View delivery slots")
    slots_parser.add_argument("--days", "-d", type=int, default=8, help="Days to show")
    slots_parser.set_defaults(func=cmd_slots)

    # Select slot
    select_parser = subparsers.add_parser("select-slot", help="Select a delivery slot")
    select_parser.add_argument("slot_id", type=int, help="Slot ID to select")
    select_parser.set_defaults(func=cmd_select_slot)

    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        return 0

    return args.func(args)


if __name__ == "__main__":
    sys.exit(main())
