"""
Add 100 spread bets to the Wake Forest vs MS State game
"""
import asyncio
import random
from datetime import datetime
from decimal import Decimal
from sqlalchemy import select

from app.database import async_session
from app.models import User, Wallet, SportEvent, SpreadBet
from app.models.spread_bet import TeamSide, SpreadBetStatus
from app.utils.security import get_password_hash


# Fake names for generating users
FIRST_NAMES = [
    "James", "Emma", "Liam", "Olivia", "Noah", "Ava", "Oliver", "Sophia",
    "Elijah", "Isabella", "Lucas", "Mia", "Mason", "Charlotte", "Ethan",
    "Amelia", "Logan", "Harper", "Aiden", "Evelyn", "Jackson", "Luna",
    "Sebastian", "Camila", "Henry", "Gianna", "Alexander", "Abigail"
]

LAST_NAMES = [
    "Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller",
    "Davis", "Rodriguez", "Martinez", "Wilson", "Anderson", "Taylor",
    "Thomas", "Moore", "Jackson", "Martin", "Lee", "Thompson", "White"
]


async def create_users_if_needed(db, count: int) -> list[User]:
    """Create additional test users if needed"""
    # Get existing users
    result = await db.execute(select(User).where(User.is_admin == False))
    existing_users = list(result.scalars().all())

    if len(existing_users) >= count:
        return existing_users[:count]

    # Create more users
    users_needed = count - len(existing_users)
    print(f"Creating {users_needed} additional test users...")

    new_users = []
    for i in range(users_needed):
        first = random.choice(FIRST_NAMES)
        last = random.choice(LAST_NAMES)
        username = f"{first.lower()}{last.lower()}{random.randint(1, 999)}"
        email = f"{username}@example.com"

        # Check if user exists
        result = await db.execute(select(User).where(User.email == email))
        if result.scalar_one_or_none():
            continue

        user = User(
            email=email,
            username=username,
            password_hash=get_password_hash("password123"),
            display_name=f"{first} {last}"
        )
        db.add(user)
        await db.flush()

        # Create wallet with random balance
        wallet = Wallet(
            user_id=user.id,
            balance=Decimal(str(random.randint(500, 5000))),
            escrow=Decimal("0.00")
        )
        db.add(wallet)
        new_users.append(user)

    await db.commit()

    # Re-fetch all users
    result = await db.execute(select(User).where(User.is_admin == False))
    return list(result.scalars().all())


async def add_bets():
    """Add 100 spread bets to Wake Forest vs MS State game"""
    async with async_session() as db:
        # Find the Wake Forest vs MS State event
        result = await db.execute(
            select(SportEvent).where(
                SportEvent.home_team == "Wake Forest",
                SportEvent.away_team == "MS State"
            )
        )
        event = result.scalar_one_or_none()

        if not event:
            print("Error: Wake Forest vs MS State event not found!")
            print("Please run init_spread_betting.py first")
            return

        print(f"Found event: {event.home_team} vs {event.away_team} (ID: {event.id})")
        print(f"Official spread: {event.official_spread}")
        print(f"Spread range: {event.min_spread} to {event.max_spread}")

        # Create/get test users (need at least 20 for variety)
        users = await create_users_if_needed(db, 20)
        print(f"Using {len(users)} users to create bets")

        # Generate 100 bets
        print("\nCreating 100 spread bets...")

        # Spread range from -10 to +10 with 0.5 increments
        spreads = [x / 2 for x in range(-20, 21)]  # -10.0 to +10.0

        # Stake amounts - realistic distribution
        stakes = [25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, 1000]

        bets_created = 0
        for i in range(100):
            creator = random.choice(users)

            # Generate spread - cluster around the official spread with some outliers
            if random.random() < 0.7:
                # 70% of bets cluster around official spread (+/- 3 points)
                spread = event.official_spread + random.choice([-3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3])
            else:
                # 30% are spread across the full range
                spread = random.choice(spreads)

            # Clamp to valid range
            spread = max(event.min_spread, min(event.max_spread, spread))

            # Random team side
            team = random.choice([TeamSide.HOME, TeamSide.AWAY])

            # Random stake - weighted toward smaller amounts
            if random.random() < 0.6:
                stake = random.choice(stakes[:6])  # 60% small bets
            elif random.random() < 0.85:
                stake = random.choice(stakes[6:10])  # 25% medium bets
            else:
                stake = random.choice(stakes[10:])  # 15% large bets

            bet = SpreadBet(
                event_id=event.id,
                spread=spread,
                team=team,
                creator_id=creator.id,
                stake_amount=Decimal(str(stake)),
                house_commission_percent=Decimal("10.00"),
                status=SpreadBetStatus.OPEN,
                created_at=datetime.utcnow()
            )
            db.add(bet)
            bets_created += 1

            if (i + 1) % 20 == 0:
                print(f"  Created {i + 1} bets...")

        await db.commit()

        print(f"\n{'='*60}")
        print(f"Successfully created {bets_created} spread bets!")
        print(f"{'='*60}")
        print(f"\nBet distribution:")
        print(f"  Event: {event.home_team} vs {event.away_team}")
        print(f"  Spreads: clustered around {event.official_spread}")
        print(f"  Stakes: $25 - $1000")
        print(f"  Teams: mixed HOME and AWAY")


async def main():
    await add_bets()


if __name__ == "__main__":
    asyncio.run(main())
