"""
Comprehensive seed data management command.

Creates all necessary data for development/testing:
- Demo tenant with domain
- Test users matching quick login (platform + tenant users)
- Resource types
- Resources (linked to staff users)
- Services
- Multiple customers
- Appointments spanning the current month
"""
import random
from datetime import timedelta
from decimal import Decimal

from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.db import connection
from django.utils import timezone
from django_tenants.utils import schema_context, tenant_context

from smoothschedule.identity.core.models import Tenant, Domain
from smoothschedule.identity.users.models import User
from smoothschedule.scheduling.schedule.models import (
    Event,
    Participant,
    Resource,
    ResourceType,
    Service,
)


class Command(BaseCommand):
    help = "Seed database with comprehensive demo data for development"

    def add_arguments(self, parser):
        parser.add_argument(
            "--clear",
            action="store_true",
            help="Clear existing data before seeding",
        )
        parser.add_argument(
            "--appointments",
            type=int,
            default=75,
            help="Number of appointments to create (default: 75)",
        )

    def handle(self, *args, **options):
        self.stdout.write("\n" + "=" * 70)
        self.stdout.write(self.style.SUCCESS("  SMOOTH SCHEDULE - SEED DATA"))
        self.stdout.write("=" * 70 + "\n")

        # Step 1: Create tenant and domain
        demo_tenant = self.create_tenant()

        # Step 2: Create platform users (in public schema)
        self.create_platform_users()

        # Step 3: Switch to tenant schema for tenant-specific data
        with tenant_context(demo_tenant):
            # Clear existing data if requested
            if options["clear"]:
                self.clear_existing_data()

            # Step 4: Create tenant users
            tenant_users = self.create_tenant_users(demo_tenant)

            # Step 5: Create resource types
            resource_types = self.create_resource_types()

            # Step 6: Create services
            services = self.create_services()

            # Step 7: Create resources (including linking staff to resources)
            resources = self.create_resources(tenant_users, resource_types)

            # Step 8: Create additional customers
            customers = self.create_customers(demo_tenant)

            # Step 9: Create appointments
            self.create_appointments(
                resources=resources,
                services=services,
                customers=customers,
                count=options["appointments"],
            )

        self.stdout.write("\n" + "=" * 70)
        self.stdout.write(self.style.SUCCESS("  SEED DATA COMPLETE!"))
        self.stdout.write("=" * 70)
        self.stdout.write("\nQuick Login Credentials:")
        self.stdout.write("  All passwords: test123")
        self.stdout.write("\nAccess URLs:")
        self.stdout.write("  Platform: http://platform.lvh.me:5173")
        self.stdout.write("  Business: http://demo.lvh.me:5173\n")

    def create_tenant(self):
        """Create public tenant (for platform/API) and demo tenant with domains."""
        self.stdout.write("\n[1/9] Creating Tenants and Domains...")

        # First create the public tenant (for platform users and API)
        try:
            public_tenant = Tenant.objects.get(schema_name="public")
            self.stdout.write(f"  {self.style.WARNING('EXISTS')} Public tenant already exists")
        except Tenant.DoesNotExist:
            public_tenant = Tenant.objects.create(
                schema_name="public",
                name="Platform",
                # Note: subscription_tier is just a label - actual plans are created via Platform Settings UI
                max_users=999,
                max_resources=999,
            )
            self.stdout.write(f"  {self.style.SUCCESS('CREATED')} Public tenant (Platform)")

        # Create domains for public tenant (platform, api, and root)
        public_domains = [
            ("platform.lvh.me", True),   # Primary for platform
            ("api.lvh.me", False),       # API subdomain
            ("lvh.me", False),           # Root domain
        ]
        for domain_name, is_primary in public_domains:
            domain, created = Domain.objects.get_or_create(
                domain=domain_name,
                defaults={
                    "tenant": public_tenant,
                    "is_primary": is_primary,
                },
            )
            if created:
                self.stdout.write(f"  {self.style.SUCCESS('CREATED')} Domain: {domain_name}")
            else:
                self.stdout.write(f"  {self.style.WARNING('EXISTS')} Domain: {domain_name}")

        # Now create the demo tenant
        try:
            tenant = Tenant.objects.get(schema_name="demo")
            self.stdout.write(f"  {self.style.WARNING('EXISTS')} Demo tenant already exists")
        except Tenant.DoesNotExist:
            tenant = Tenant.objects.create(
                schema_name="demo",
                name="Demo Company",
                # Note: No subscription_tier set - plans are created via Platform Settings UI
                # These feature flags are set directly for demo purposes
                max_users=25,
                max_resources=50,
                timezone="America/Denver",
                can_use_plugins=True,
                can_use_tasks=True,
                can_accept_payments=True,
                can_customize_booking_page=True,
                initial_setup_complete=True,
            )
            self.stdout.write(f"  {self.style.SUCCESS('CREATED')} Demo tenant")

        # Create domain for demo tenant
        domain, created = Domain.objects.get_or_create(
            domain="demo.lvh.me",
            defaults={
                "tenant": tenant,
                "is_primary": True,
            },
        )
        if created:
            self.stdout.write(f"  {self.style.SUCCESS('CREATED')} Domain: demo.lvh.me")
        else:
            self.stdout.write(f"  {self.style.WARNING('EXISTS')} Domain: demo.lvh.me")

        return tenant

    def create_platform_users(self):
        """Create platform-level users (superuser, manager, sales, support)."""
        self.stdout.write("\n[2/9] Creating Platform Users...")

        platform_users = [
            {
                "username": "poduck",
                "email": "poduck@gmail.com",
                "password": "starry12",
                "role": User.Role.SUPERUSER,
                "first_name": "Poduck",
                "last_name": "Admin",
                "tenant": None,
            },
            {
                "username": "superuser@platform.com",
                "email": "superuser@platform.com",
                "password": "test123",
                "role": User.Role.SUPERUSER,
                "first_name": "Super",
                "last_name": "User",
                "tenant": None,
            },
            {
                "username": "manager@platform.com",
                "email": "manager@platform.com",
                "password": "test123",
                "role": User.Role.PLATFORM_MANAGER,
                "first_name": "Platform",
                "last_name": "Manager",
                "tenant": None,
            },
            {
                "username": "sales@platform.com",
                "email": "sales@platform.com",
                "password": "test123",
                "role": User.Role.PLATFORM_SALES,
                "first_name": "Sales",
                "last_name": "Rep",
                "tenant": None,
            },
            {
                "username": "support@platform.com",
                "email": "support@platform.com",
                "password": "test123",
                "role": User.Role.PLATFORM_SUPPORT,
                "first_name": "Support",
                "last_name": "Agent",
                "tenant": None,
            },
        ]

        for user_data in platform_users:
            password = user_data.pop("password")
            user, created = User.objects.get_or_create(
                username=user_data["username"],
                defaults=user_data,
            )
            if created:
                user.set_password(password)
                user.save()
                status = self.style.SUCCESS("CREATED")
            else:
                status = self.style.WARNING("EXISTS")
            self.stdout.write(f"  {status} {user.email} ({user.get_role_display()})")

    def create_tenant_users(self, tenant):
        """Create tenant-level users (owner, manager, staff)."""
        self.stdout.write("\n[3/9] Creating Tenant Users...")

        tenant_users = [
            {
                "username": "owner@demo.com",
                "email": "owner@demo.com",
                "password": "test123",
                "role": User.Role.TENANT_OWNER,
                "first_name": "Business",
                "last_name": "Owner",
                "tenant": tenant,
                "phone": "555-100-0001",
            },
            {
                "username": "manager@demo.com",
                "email": "manager@demo.com",
                "password": "test123",
                "role": User.Role.TENANT_MANAGER,
                "first_name": "Business",
                "last_name": "Manager",
                "tenant": tenant,
                "phone": "555-100-0002",
            },
            {
                "username": "staff@demo.com",
                "email": "staff@demo.com",
                "password": "test123",
                "role": User.Role.TENANT_STAFF,
                "first_name": "Staff",
                "last_name": "Member",
                "tenant": tenant,
                "phone": "555-100-0003",
            },
        ]

        created_users = {}
        for user_data in tenant_users:
            password = user_data.pop("password")
            user, created = User.objects.get_or_create(
                username=user_data["username"],
                defaults=user_data,
            )
            if created:
                user.set_password(password)
                user.save()
                status = self.style.SUCCESS("CREATED")
            else:
                status = self.style.WARNING("EXISTS")
            self.stdout.write(f"  {status} {user.email} ({user.get_role_display()})")
            created_users[user_data["role"]] = user

        return created_users

    def create_resource_types(self):
        """Create resource types."""
        self.stdout.write("\n[4/9] Creating Resource Types...")

        resource_types_data = [
            {
                "name": "Staff",
                "category": ResourceType.Category.STAFF,
                "description": "Staff members who provide services",
                "is_default": True,
            },
            {
                "name": "Room",
                "category": ResourceType.Category.OTHER,
                "description": "Treatment or meeting rooms",
                "is_default": True,
            },
            {
                "name": "Equipment",
                "category": ResourceType.Category.OTHER,
                "description": "Shared equipment",
                "is_default": False,
            },
        ]

        resource_types = {}
        for rt_data in resource_types_data:
            rt, created = ResourceType.objects.get_or_create(
                name=rt_data["name"],
                defaults=rt_data,
            )
            status = self.style.SUCCESS("CREATED") if created else self.style.WARNING("EXISTS")
            self.stdout.write(f"  {status} {rt.name} ({rt.get_category_display()})")
            resource_types[rt_data["name"]] = rt

        return resource_types

    def create_services(self):
        """Create services."""
        self.stdout.write("\n[5/9] Creating Services...")

        services_data = [
            {
                "name": "Consultation",
                "description": "Initial consultation to discuss your needs",
                "duration": 30,
                "price_cents": 0,
                "display_order": 1,
            },
            {
                "name": "Standard Appointment",
                "description": "Standard 1-hour appointment",
                "duration": 60,
                "price_cents": 7500,  # $75.00
                "display_order": 2,
            },
            {
                "name": "Extended Session",
                "description": "Extended 90-minute session",
                "duration": 90,
                "price_cents": 11000,  # $110.00
                "display_order": 3,
            },
            {
                "name": "Quick Check-in",
                "description": "Brief 15-minute check-in",
                "duration": 15,
                "price_cents": 2500,  # $25.00
                "display_order": 4,
            },
            {
                "name": "Premium Package",
                "description": "Premium 2-hour comprehensive service",
                "duration": 120,
                "price_cents": 20000,  # $200.00
                "display_order": 5,
                "variable_pricing": True,
                "deposit_amount_cents": 5000,  # $50 deposit
            },
        ]

        services = []
        for svc_data in services_data:
            service, created = Service.objects.get_or_create(
                name=svc_data["name"],
                defaults=svc_data,
            )
            status = self.style.SUCCESS("CREATED") if created else self.style.WARNING("EXISTS")
            price = svc_data["price_cents"] / 100
            self.stdout.write(f"  {status} {service.name} ({svc_data['duration']} min, ${price:.2f})")
            services.append(service)

        return services

    def create_resources(self, tenant_users, resource_types):
        """Create resources including staff-linked resources."""
        self.stdout.write("\n[6/9] Creating Resources...")

        staff_type = resource_types.get("Staff")
        room_type = resource_types.get("Room")
        equipment_type = resource_types.get("Equipment")

        resources = []

        # Create staff resources linked to users
        staff_resources = [
            {
                "name": "Staff Member",
                "user": tenant_users.get(User.Role.TENANT_STAFF),
                "description": "General staff member",
                "resource_type": staff_type,
                "type": Resource.Type.STAFF,
            },
            {
                "name": "Business Manager",
                "user": tenant_users.get(User.Role.TENANT_MANAGER),
                "description": "Business manager - handles VIP appointments",
                "resource_type": staff_type,
                "type": Resource.Type.STAFF,
            },
        ]

        for res_data in staff_resources:
            if res_data["user"]:
                resource, created = Resource.objects.get_or_create(
                    user=res_data["user"],
                    defaults=res_data,
                )
                status = self.style.SUCCESS("CREATED") if created else self.style.WARNING("EXISTS")
                self.stdout.write(f"  {status} {resource.name} (Staff - linked to {res_data['user'].email})")
                resources.append(resource)

        # Create additional staff resources (not linked to quick login users)
        additional_staff = [
            {"name": "Sarah Johnson", "description": "Senior specialist"},
            {"name": "Mike Chen", "description": "Team lead"},
            {"name": "Emily Rodriguez", "description": "Junior specialist"},
        ]

        for staff_data in additional_staff:
            # Create a user for this staff member
            email = staff_data["name"].lower().replace(" ", ".") + "@demo.com"
            first_name, last_name = staff_data["name"].split(" ", 1)

            user, _ = User.objects.get_or_create(
                username=email,
                defaults={
                    "email": email,
                    "first_name": first_name,
                    "last_name": last_name,
                    "role": User.Role.TENANT_STAFF,
                    "tenant_id": connection.tenant.id if hasattr(connection, "tenant") else None,
                },
            )
            if user.pk:
                user.set_password("test123")
                user.save()

            resource, created = Resource.objects.get_or_create(
                name=staff_data["name"],
                defaults={
                    "user": user,
                    "description": staff_data["description"],
                    "resource_type": staff_type,
                    "type": Resource.Type.STAFF,
                },
            )
            status = self.style.SUCCESS("CREATED") if created else self.style.WARNING("EXISTS")
            self.stdout.write(f"  {status} {resource.name} (Staff)")
            resources.append(resource)

        # Create room resources
        room_resources = [
            {"name": "Room A", "description": "Main meeting room", "max_concurrent_events": 1},
            {"name": "Room B", "description": "Private consultation room", "max_concurrent_events": 1},
            {"name": "Conference Room", "description": "Large conference room", "max_concurrent_events": 3},
        ]

        for room_data in room_resources:
            resource, created = Resource.objects.get_or_create(
                name=room_data["name"],
                defaults={
                    "description": room_data["description"],
                    "resource_type": room_type,
                    "type": Resource.Type.ROOM,
                    "max_concurrent_events": room_data.get("max_concurrent_events", 1),
                },
            )
            status = self.style.SUCCESS("CREATED") if created else self.style.WARNING("EXISTS")
            self.stdout.write(f"  {status} {resource.name} (Room)")
            resources.append(resource)

        # Create equipment resource
        equipment, created = Resource.objects.get_or_create(
            name="Projector",
            defaults={
                "description": "Portable projector for presentations",
                "resource_type": equipment_type,
                "type": Resource.Type.EQUIPMENT,
                "max_concurrent_events": 1,
            },
        )
        status = self.style.SUCCESS("CREATED") if created else self.style.WARNING("EXISTS")
        self.stdout.write(f"  {status} {equipment.name} (Equipment)")
        resources.append(equipment)

        return resources

    def create_customers(self, tenant):
        """Create customer users."""
        self.stdout.write("\n[7/9] Creating Customers...")

        # First add the quick login customer
        customer_demo, created = User.objects.get_or_create(
            username="customer@demo.com",
            defaults={
                "email": "customer@demo.com",
                "first_name": "Demo",
                "last_name": "Customer",
                "role": User.Role.CUSTOMER,
                "tenant": tenant,
                "phone": "555-200-0001",
            },
        )
        if created:
            customer_demo.set_password("test123")
            customer_demo.save()
            status = self.style.SUCCESS("CREATED")
        else:
            status = self.style.WARNING("EXISTS")
        self.stdout.write(f"  {status} {customer_demo.email} (Quick Login Customer)")

        customers = [customer_demo]

        # Create additional customers
        customer_data = [
            ("Alice", "Williams", "alice.williams@example.com", "555-200-0002"),
            ("Bob", "Martinez", "bob.martinez@example.com", "555-200-0003"),
            ("Carol", "Davis", "carol.davis@example.com", "555-200-0004"),
            ("David", "Lee", "david.lee@example.com", "555-200-0005"),
            ("Emma", "Thompson", "emma.thompson@example.com", "555-200-0006"),
            ("Frank", "Wilson", "frank.wilson@example.com", "555-200-0007"),
            ("Grace", "Kim", "grace.kim@example.com", "555-200-0008"),
            ("Henry", "Brown", "henry.brown@example.com", "555-200-0009"),
            ("Ivy", "Chen", "ivy.chen@example.com", "555-200-0010"),
            ("Jack", "Taylor", "jack.taylor@example.com", "555-200-0011"),
            ("Karen", "Johnson", "karen.johnson@example.com", "555-200-0012"),
            ("Leo", "Garcia", "leo.garcia@example.com", "555-200-0013"),
            ("Maria", "Rodriguez", "maria.rodriguez@example.com", "555-200-0014"),
            ("Nathan", "White", "nathan.white@example.com", "555-200-0015"),
        ]

        for first_name, last_name, email, phone in customer_data:
            user, created = User.objects.get_or_create(
                username=email,
                defaults={
                    "email": email,
                    "first_name": first_name,
                    "last_name": last_name,
                    "role": User.Role.CUSTOMER,
                    "tenant": tenant,
                    "phone": phone,
                },
            )
            if created:
                user.set_password("test123")
                user.save()
                status = self.style.SUCCESS("CREATED")
            else:
                status = self.style.WARNING("EXISTS")
            self.stdout.write(f"  {status} {user.email}")
            customers.append(user)

        return customers

    def create_appointments(self, resources, services, customers, count):
        """Create demo appointments."""
        self.stdout.write(f"\n[8/9] Creating {count} Appointments...")

        # Filter to only staff resources for appointments
        staff_resources = [r for r in resources if r.type == Resource.Type.STAFF]
        if not staff_resources:
            staff_resources = resources[:3]  # Fallback

        # Get content types
        resource_ct = ContentType.objects.get_for_model(Resource)
        user_ct = ContentType.objects.get_for_model(User)

        # Get time range (current month + next month)
        now = timezone.now()
        start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        if now.month == 12:
            end_date = start_date.replace(year=now.year + 1, month=2, day=1)
        elif now.month == 11:
            end_date = start_date.replace(year=now.year + 1, month=1, day=1)
        else:
            end_date = start_date.replace(month=now.month + 2, day=1)

        days_range = (end_date - start_date).days

        statuses = [
            Event.Status.SCHEDULED,
            Event.Status.SCHEDULED,
            Event.Status.SCHEDULED,
            Event.Status.COMPLETED,
            Event.Status.COMPLETED,
            Event.Status.CANCELED,
        ]

        created_count = 0
        for i in range(count):
            # Random date in range
            random_day = random.randint(0, days_range - 1)
            appointment_date = start_date + timedelta(days=random_day)

            # Random business hours (8am - 6pm)
            hour = random.randint(8, 17)
            minute = random.choice([0, 15, 30, 45])
            start_time = appointment_date.replace(hour=hour, minute=minute)

            # Pick random service, resource, customer
            service = random.choice(services)
            resource = random.choice(staff_resources)
            customer = random.choice(customers)

            # Determine status
            status = random.choice(statuses)
            if start_time < now and status == Event.Status.SCHEDULED:
                status = Event.Status.COMPLETED
            elif start_time > now and status in [Event.Status.COMPLETED, Event.Status.CANCELED]:
                status = Event.Status.SCHEDULED

            # Calculate end time
            end_time = start_time + timedelta(minutes=service.duration)

            # Create event
            event = Event.objects.create(
                title=f"{customer.full_name} - {service.name}",
                start_time=start_time,
                end_time=end_time,
                status=status,
                service=service,
                notes=f"Booked service: {service.name}\nCustomer phone: {customer.phone}",
            )

            # Create resource participant
            Participant.objects.create(
                event=event,
                role=Participant.Role.RESOURCE,
                content_type=resource_ct,
                object_id=resource.id,
            )

            # Create customer participant
            Participant.objects.create(
                event=event,
                role=Participant.Role.CUSTOMER,
                content_type=user_ct,
                object_id=customer.id,
            )

            created_count += 1

        self.stdout.write(
            f"  {self.style.SUCCESS('CREATED')} {created_count} appointments across {days_range} days"
        )

        # Show summary
        self.stdout.write("\n[9/9] Summary Statistics...")
        scheduled = Event.objects.filter(status=Event.Status.SCHEDULED).count()
        completed = Event.objects.filter(status=Event.Status.COMPLETED).count()
        canceled = Event.objects.filter(status=Event.Status.CANCELED).count()

        self.stdout.write(f"  Scheduled: {scheduled}")
        self.stdout.write(f"  Completed: {completed}")
        self.stdout.write(f"  Canceled: {canceled}")

    def clear_existing_data(self):
        """Clear existing demo data."""
        self.stdout.write("\n  Clearing existing data...")

        # Delete in order to respect foreign keys
        deleted = Participant.objects.all().delete()[0]
        self.stdout.write(f"    Deleted {deleted} participants")

        deleted = Event.objects.all().delete()[0]
        self.stdout.write(f"    Deleted {deleted} events")

        # Don't delete resources/services/customers - just events
        self.stdout.write("    (Keeping resources, services, and customers)")
