"""First-run data. seed_base is safe for real stores; seed_demo only runs when DEMO=1."""
import random
from datetime import timedelta
from decimal import Decimal

from sqlalchemy import select
from sqlalchemy.orm import Session

from . import security
from .models import (Category, DeliveryZone, Order, OrderEvent, OrderItem, Product,
                     StockMovement, Supplier, User, now)
from .services import get_setting, set_setting

DEPARTMENTS = ["Pasta & Grains", "Canned & Tinned", "Breakfast", "Drinks", "Oils & Sauces", "Snacks & Biscuits",
               "Baking & Spreads", "Household"]
ZONES = [("Accra Central & Osu", "15.00", "Same day"), ("East Legon & Airport", "20.00", "Same day"),
         ("Tema & Spintex", "30.00", "Same day"), ("Kasoa & Weija", "35.00", "Next day")]

# name, brand, size, category, price, cost, stock, reorder, badge
CATALOG = [
    ("Golden Penny Spaghetti", "Golden Penny", "500 g", 0, "18.50", "13.20", 120, 30, "Popular"),
    ("Tilda Pure Basmati Rice", "Tilda", "1 kg", 0, "89.00", "68.00", 40, 12, "Imported"),
    ("Royal Stallion Long Grain Rice", "Royal Stallion", "5 kg", 0, "165.00", "138.00", 55, 15, ""),
    ("Barilla Penne Rigate", "Barilla", "500 g", 0, "36.00", "26.50", 36, 10, "Imported"),
    ("Indomie Chicken Noodles (carton)", "Indomie", "40 x 70 g", 0, "135.00", "112.00", 30, 8, "Popular"),
    ("Heinz Baked Beans", "Heinz", "415 g", 1, "24.00", "17.50", 48, 15, "Imported"),
    ("Geisha Mackerel in Tomato Sauce", "Geisha", "155 g", 1, "14.50", "10.80", 150, 40, "Popular"),
    ("Gino Tomato Paste", "Gino", "400 g", 1, "19.00", "14.20", 90, 24, ""),
    ("Del Monte Sweetcorn", "Del Monte", "340 g", 1, "22.00", "16.10", 8, 12, "Low stock"),
    ("Sardines in Oil", "Titus", "125 g", 1, "11.50", "8.40", 110, 30, ""),
    ("Kellogg's Corn Flakes", "Kellogg's", "500 g", 2, "76.00", "58.00", 7, 10, "Low stock"),
    ("Nido Fortified Milk", "Nestlé", "400 g", 2, "71.00", "55.00", 6, 12, "Low stock"),
    ("Quaker Rolled Oats", "Quaker", "500 g", 2, "42.00", "31.00", 44, 12, ""),
    ("Cerelac Wheat & Milk", "Nestlé", "400 g", 2, "58.00", "44.00", 52, 15, "Favourite"),
    ("Milo Active-Go", "Nestlé", "400 g", 3, "62.00", "47.00", 70, 20, "Favourite"),
    ("Lipton Yellow Label Tea", "Lipton", "100 bags", 3, "38.00", "28.00", 64, 15, ""),
    ("Bournvita", "Cadbury", "450 g", 3, "55.00", "41.00", 38, 12, ""),
    ("Ribena Blackcurrant", "Ribena", "1 L", 3, "34.00", "25.00", 26, 10, "Imported"),
    ("Voltic Natural Water (carton)", "Voltic", "12 x 1.5 L", 3, "48.00", "36.00", 80, 20, ""),
    ("Frytol Vegetable Oil", "Frytol", "3 L", 4, "105.00", "86.00", 42, 12, "Popular"),
    ("Kings Vegetable Oil", "Kings", "5 L", 4, "168.00", "139.00", 28, 8, ""),
    ("Maggi Star Cubes", "Maggi", "100 cubes", 4, "29.00", "21.00", 100, 25, "Popular"),
    ("Heinz Tomato Ketchup", "Heinz", "570 g", 4, "39.00", "29.00", 34, 10, "Imported"),
    ("Shito Hot Pepper Sauce", "Maame Pat", "300 g", 4, "32.00", "22.00", 46, 12, "Local favourite"),
    ("Pringles Original", "Pringles", "165 g", 5, "46.00", "35.00", 30, 10, "Imported"),
    ("Digestive Biscuits", "McVitie's", "400 g", 5, "34.00", "25.00", 40, 10, "Imported"),
    ("Cabin Biscuits", "Cabin", "200 g", 5, "9.50", "6.80", 140, 40, ""),
    ("Dangote Sugar", "Dangote", "1 kg", 6, "27.00", "21.00", 90, 25, ""),
    ("Blue Band Margarine", "Blue Band", "450 g", 6, "31.00", "23.00", 4, 10, "Low stock"),
    ("Nutella Hazelnut Spread", "Ferrero", "350 g", 6, "88.00", "68.00", 22, 8, "Imported"),
    ("Omo Washing Powder", "Omo", "2 kg", 7, "74.00", "56.00", 33, 10, ""),
    ("Sunlight Dishwashing Liquid", "Sunlight", "750 ml", 7, "21.00", "15.00", 48, 12, ""),
]
SUPPLIERS = [("Accra Wholesale Traders", "Kwame Boateng", "0244000111", "Ghana", 3),
             ("Global Provisions Ltd (imports)", "Sarah Mensah", "0200000222", "United Kingdom", 21),
             ("Tema Distribution Co.", "Yaw Asare", "0555000333", "Ghana", 5)]
FIRST = ["Ama", "Kofi", "Akosua", "Kwesi", "Esi", "Yaw", "Abena", "Kojo", "Efua", "Nana", "Adwoa", "Kweku", "Maame", "Femi", "Selina"]
LAST = ["Mensah", "Owusu", "Boateng", "Asante", "Appiah", "Agyeman", "Osei", "Darko", "Quaye", "Tetteh"]


def seed_base(db: Session):
    """Nothing here is fake data: only the starting zones, settings and department names."""
    if not db.scalar(select(DeliveryZone.id)):
        for n, fee, eta in ZONES:
            db.add(DeliveryZone(name=n, fee=Decimal(fee), eta=eta))
    if not get_setting(db, "store_name"):
        set_setting(db, "store_name", "Abrokyire Aba Ghana")
        set_setting(db, "free_delivery_over", "250")
        set_setting(db, "momo_instructions", "After you order, send the total to our Mobile Money number and use your order number as the reference.")
    if not db.scalar(select(Category.id)):
        for i, n in enumerate(DEPARTMENTS):
            db.add(Category(name=n, sort=i))
    db.commit()


def seed_demo(db: Session):
    """Sample shop with 60 days of orders so every chart and KPI has real figures behind it."""
    if db.scalar(select(Product.id)):
        return
    rnd = random.Random(2026)
    pw = security.hash_password("Demo1234")
    db.add_all([User(name="Store Owner", email="owner@elitemart.demo", role="owner", password_hash=pw),
                User(name="Ama (Store Staff)", email="staff@elitemart.demo", role="staff", password_hash=pw)])
    customers = [User(name=f"{rnd.choice(FIRST)} {rnd.choice(LAST)}", email=f"customer{i}@elitemart.demo",
                      phone=f"024{rnd.randint(1000000, 9999999)}", address=f"{rnd.randint(1, 80)} Demo Street, Accra",
                      password_hash=pw) for i in range(1, 13)]
    customers[0].name, customers[0].email = "Demo Customer", "customer@elitemart.demo"
    db.add_all(customers)
    sups = [Supplier(name=n, contact=c, phone=p, country=co, lead_days=d) for n, c, p, co, d in SUPPLIERS]
    db.add_all(sups)
    db.flush()
    cats = db.scalars(select(Category).order_by(Category.sort)).all()
    products = []
    for i, (n, b, sz, c, price, cost, stock, re, badge) in enumerate(CATALOG, start=1):
        products.append(Product(sku=f"EM{i:03d}", name=n, brand=b, size=sz, category_id=cats[c].id, price=Decimal(price),
                                cost=Decimal(cost), stock=0, reorder_level=re, badge=badge,
                                description=f"{n.split('(')[0].strip()} - {sz}. Selected for quality and everyday value.",
                                supplier_id=sups[1].id if badge == "Imported" else sups[rnd.choice([0, 2])].id))
    db.add_all(products)
    db.flush()
    zones = db.scalars(select(DeliveryZone)).all()
    today = now()
    # Build 60 days of history by selling from a bigger opening stock, then set today's stock level.
    sold = {p.id: 0 for p in products}
    for back in range(59, -1, -1):
        day = today - timedelta(days=back)
        busy = 1.0 + (0.5 if day.weekday() in (4, 5) else 0) + (60 - back) / 120
        for _ in range(int(rnd.randint(4, 9) * busy)):
            cust = rnd.choice(customers + [None] * 5)
            zone = rnd.choice(zones)
            lines = rnd.sample(products, rnd.randint(1, 5))
            sub = Decimal(0)
            items = []
            for p in lines:
                q = rnd.choice([1, 1, 1, 2, 2, 3, 6])
                items.append((p, q))
                sub += p.price * q
            fee = Decimal(0) if sub >= 250 else zone.fee
            when = day.replace(hour=rnd.randint(8, 21), minute=rnd.randint(0, 59), second=rnd.randint(0, 59))
            if when > today:
                when = today - timedelta(minutes=rnd.randint(1, 90))
            cancelled = rnd.random() < 0.04
            if back > 2:
                status = "cancelled" if cancelled else "delivered"
            else:
                status = rnd.choice(["pending", "confirmed", "packed", "out_for_delivery", "delivered"]) if not cancelled else "cancelled"
            method = rnd.choice(["momo", "momo", "cod"])
            name = cust.name if cust else f"{rnd.choice(FIRST)} {rnd.choice(LAST)}"
            phone = cust.phone if cust and cust.phone else f"055{rnd.randint(1000000, 9999999)}"
            o = Order(number=f"EM-{when:%y%m%d}-{rnd.randint(0, 65535):04X}", user_id=cust.id if cust else None,
                      customer_name=name, phone=phone, address=f"{rnd.randint(1, 120)} {rnd.choice(['Ring Road', 'Oxford St', 'Spintex Rd', 'Labone', 'Cantonments'])}, {zone.name}",
                      zone_id=zone.id, zone_name=zone.name, subtotal=sub, delivery_fee=fee, total=sub + fee,
                      status=status, payment_method=method,
                      payment_status="refunded" if cancelled and method == "momo" else ("paid" if (status == "delivered" or (method == "momo" and not cancelled and rnd.random() < .8)) else "unpaid"),
                      created_at=when)
            db.add(o)
            db.flush()
            for p, q in items:
                db.add(OrderItem(order_id=o.id, product_id=p.id, name=p.name, category=cats[CATALOG[products.index(p)][3]].name,
                                 quantity=q, unit_price=p.price, unit_cost=p.cost))
                if not cancelled:
                    sold[p.id] += q
            db.add(OrderEvent(order_id=o.id, status="pending", note="Order placed", by=name, at=when))
            if status != "pending":
                db.add(OrderEvent(order_id=o.id, status=status, by="Ama (Store Staff)", at=when + timedelta(hours=2)))
    for (n, b, sz, c, price, cost, stock, re, badge), p in zip(CATALOG, products):
        p.stock = stock
        db.add(StockMovement(product_id=p.id, change=stock + sold[p.id], after=stock + sold[p.id],
                             reason="adjust", ref="opening stock", by="Demo setup", at=today - timedelta(days=60)))
        if sold[p.id]:
            db.add(StockMovement(product_id=p.id, change=-sold[p.id], after=stock, reason="sale",
                                 ref="60 days of demo orders", by="Demo setup", at=today))
    db.commit()
