from datetime import timedelta
from decimal import Decimal

from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils import timezone
from django.utils.text import slugify

from apps.business.marketplace.models import (
    Brand,
    Category,
    OrderItem,
    SubCategory,
    Vendor,
    VendorEarning,
    VendorInventory,
)
from apps.business.orders.models import Order
from apps.business.products.models import Product
from apps.geo.models import (
    Country,
    District,
    FranchiseAssignment,
    FranchisePincodeCoverage,
    FranchiseStore,
    FranchiseStoreEarning,
    FranchiseStoreInventory,
    Mandal,
    Pincode,
    State,
)
from apps.telemetry.services import (
    aggregate_kpis,
    compute_cohort_snapshots,
    compute_funnel_snapshots,
    compute_retention_snapshots,
    detect_anomalies,
)


class Command(BaseCommand):
    help = 'Seed E2E marketplace/vendor/franchise data and telemetry analytics snapshots'

    def add_arguments(self, parser):
        parser.add_argument('--admin-mobile', type=str, default='8668192080')
        parser.add_argument('--customer-count', type=int, default=6)
        parser.add_argument('--days', type=int, default=35)

    @transaction.atomic
    def handle(self, *args, **options):
        admin_mobile = options['admin_mobile']
        customer_count = max(3, options['customer_count'])
        days = max(7, options['days'])

        User = get_user_model()

        admin_user, _ = User.objects.get_or_create(
            mobile=admin_mobile,
            defaults={
                'email': f'admin{admin_mobile}@truewave.local',
                'first_name': 'Main',
                'last_name': 'Admin',
                'is_staff': True,
                'is_superuser': True,
                'role': 'ADMIN',
                'is_mobile_verified': True,
            },
        )
        if not admin_user.is_staff or not admin_user.is_superuser:
            admin_user.is_staff = True
            admin_user.is_superuser = True
            admin_user.role = 'ADMIN'
            admin_user.save(update_fields=['is_staff', 'is_superuser', 'role', 'updated_at'])

        country, _ = Country.objects.get_or_create(code='IN', defaults={'name': 'India'})
        state, _ = State.objects.get_or_create(name='Telangana', country=country)
        district, _ = District.objects.get_or_create(name='Hyderabad', state=state)
        mandal, _ = Mandal.objects.get_or_create(name='Madhapur', district=district)
        pincode, _ = Pincode.objects.get_or_create(
            code='500081',
            location='Madhapur',
            defaults={
                'country': country,
                'state': state,
                'district': district,
            },
        )

        store, _ = FranchiseStore.objects.get_or_create(
            code='FS-HYD-001',
            defaults={
                'name': 'Truewave Madhapur Franchise',
                'country': country,
                'state': state,
                'district': district,
                'mandal': mandal,
                'pincode': pincode,
                'address_line1': 'HiTech City Main Road',
                'contact_name': 'Franchise Manager',
                'contact_mobile': '9000012345',
            },
        )

        FranchiseAssignment.objects.get_or_create(
            user=admin_user,
            territory_level=FranchiseAssignment.TerritoryLevel.DISTRICT,
            district=district,
            defaults={
                'store': store,
                'role_title': 'Regional Franchise Head',
                'assignment_reason': 'E2E telemetry and marketplace coverage seed',
                'assigned_by': admin_user,
            },
        )

        FranchisePincodeCoverage.objects.get_or_create(
            store=store,
            pincode_code='500081',
            defaults={
                'pincode': pincode,
                'city': 'Hyderabad',
                'state': 'Telangana',
                'is_serviceable': True,
            },
        )

        cat_health, _ = Category.objects.get_or_create(
            slug='health-wellness',
            defaults={'name': 'Health & Wellness', 'is_active': True, 'display_order': 1},
        )
        cat_grocery, _ = Category.objects.get_or_create(
            slug='daily-grocery',
            defaults={'name': 'Daily Grocery', 'is_active': True, 'display_order': 2},
        )

        sub_health, _ = SubCategory.objects.get_or_create(
            category=cat_health,
            slug='supplements',
            defaults={'name': 'Supplements', 'is_active': True},
        )
        sub_grocery, _ = SubCategory.objects.get_or_create(
            category=cat_grocery,
            slug='staples',
            defaults={'name': 'Staples', 'is_active': True},
        )

        brand_a, _ = Brand.objects.get_or_create(slug='truewave-nutra', defaults={'name': 'Truewave Nutra'})
        brand_b, _ = Brand.objects.get_or_create(slug='truewave-home', defaults={'name': 'Truewave Home'})

        vendor_users = []
        for idx in range(2):
            vendor_mobile = f'90000010{idx + 1}'
            u, _ = User.objects.get_or_create(
                mobile=vendor_mobile,
                defaults={
                    'email': f'vendor{idx + 1}@truewave.local',
                    'first_name': 'Vendor',
                    'last_name': str(idx + 1),
                    'role': 'VENDOR',
                    'is_mobile_verified': True,
                },
            )
            vendor_users.append(u)

        vendors = []
        for idx, u in enumerate(vendor_users, start=1):
            vendor, _ = Vendor.objects.get_or_create(
                user=u,
                defaults={
                    'company_name': f'Truewave Vendor {idx} Pvt Ltd',
                    'company_registration_number': f'TWVND{idx:04d}',
                    'tax_id': f'GSTTWMV{idx:04d}',
                    'business_email': f'vendor{idx}@business.truewave.local',
                    'business_phone': f'90000020{idx}',
                    'business_address': 'Plot 14, Financial District, Hyderabad',
                    'city': 'Hyderabad',
                    'state': 'Telangana',
                    'pincode': '500081',
                    'country': 'India',
                    'store_name': f'Truewave Vendor Store {idx}',
                    'store_description': 'E2E seeded vendor storefront',
                    'status': 'APPROVED',
                    'is_active': True,
                    'approval_date': timezone.now(),
                },
            )
            if vendor.status != 'APPROVED' or not vendor.is_active:
                vendor.status = 'APPROVED'
                vendor.is_active = True
                vendor.approval_date = timezone.now()
                vendor.save(update_fields=['status', 'is_active', 'approval_date', 'updated_at'])
            vendors.append(vendor)

        products = []
        product_specs = [
            ('Daily Protein Mix', 'daily-protein-mix', Decimal('899.00'), Decimal('1299.00'), cat_health, sub_health, brand_a, vendors[0]),
            ('Herbal Immunity Booster', 'herbal-immunity-booster', Decimal('649.00'), Decimal('899.00'), cat_health, sub_health, brand_a, vendors[1]),
            ('Premium Cooking Oil 5L', 'premium-cooking-oil-5l', Decimal('1199.00'), Decimal('1499.00'), cat_grocery, sub_grocery, brand_b, vendors[0]),
            ('Whole Grain Nutrition Pack', 'whole-grain-nutrition-pack', Decimal('499.00'), Decimal('699.00'), cat_grocery, sub_grocery, brand_b, vendors[1]),
        ]
        for idx, (name, slug, base_cost, mrp, category, subcategory, brand, vendor) in enumerate(product_specs, start=1):
            p, _ = Product.objects.get_or_create(
                slug=slugify(slug),
                defaults={
                    'name': name,
                    'category': Product.Category.PHYSICAL,
                    'product_type': Product.ProductType.STANDARD,
                    'description': f'{name} seeded for E2E analytics and admin product dashboards.',
                    'base_cost': base_cost,
                    'gst_percentage': Decimal('18.000'),
                    'sku': f'TWM-MP-{idx:03d}',
                    'mrp': mrp,
                    'marketplace_category': category,
                    'marketplace_subcategory': subcategory,
                    'brand': brand,
                    'vendor': vendor,
                    'vendor_managed': True,
                    'franchise_fulfilled': True,
                    'marketplace_status': 'ACTIVE',
                    'is_active': True,
                    'is_featured': idx % 2 == 0,
                },
            )
            products.append(p)
            VendorInventory.objects.update_or_create(
                vendor=vendor,
                product=p,
                defaults={
                    'stock': 250,
                    'reserved_stock': 15,
                    'reorder_point': 25,
                    'last_restocked': timezone.now() - timedelta(days=2),
                },
            )
            FranchiseStoreInventory.objects.update_or_create(
                store=store,
                product=p,
                defaults={
                    'stock': 180,
                    'reserved_stock': 10,
                    'reorder_point': 20,
                    'max_stock_level': 500,
                    'auto_reorder': True,
                    'last_restocked': timezone.now() - timedelta(days=1),
                },
            )

        customers = []
        for idx in range(customer_count):
            mobile = f'8110001{idx:03d}'
            user, _ = User.objects.get_or_create(
                mobile=mobile,
                defaults={
                    'email': f'customer{idx + 1}@truewave.local',
                    'first_name': 'Customer',
                    'last_name': str(idx + 1),
                    'role': 'USER',
                    'is_mobile_verified': True,
                    'pincode': pincode,
                    'city': 'Hyderabad',
                    'state': 'Telangana',
                    'country': 'India',
                },
            )
            customers.append(user)

        order_count = 0
        for day_back in range(days, 0, -1):
            ordered_at = timezone.now() - timedelta(days=day_back)
            for idx, customer in enumerate(customers):
                primary_product = products[(idx + day_back) % len(products)]
                ref = f'E2E-{ordered_at.strftime("%Y%m%d")}-{customer.mobile}-{idx}'
                order, created = Order.objects.get_or_create(
                    reference_id=ref,
                    defaults={
                        'user': customer,
                        'product': primary_product,
                        'amount': primary_product.base_cost,
                        'voucher_amount': Decimal('0.00'),
                        'super_coin_amount': Decimal('15.00'),
                        'cash_amount': primary_product.base_cost - Decimal('15.00'),
                        'status': 'COMPLETED',
                        'order_type': 'RETAIL',
                        'payment_method': 'main_wallet',
                        'fulfillment_mode': 'STORE_DELIVERY',
                        'franchise_fulfillment_status': 'DELIVERED',
                        'delivery_store': store,
                        'client_reference_id': f'CL-{ref}',
                    },
                )
                if created:
                    Order.objects.filter(pk=order.pk).update(created_at=ordered_at, updated_at=ordered_at)
                vendor = primary_product.vendor
                unit_price = primary_product.base_cost
                quantity = 1 + (idx % 2)
                total_price = unit_price * quantity

                OrderItem.objects.get_or_create(
                    order=order,
                    product=primary_product,
                    defaults={
                        'quantity': quantity,
                        'unit_price': unit_price,
                        'total_price': total_price,
                        'discount_amount': Decimal('25.00'),
                        'tax_amount': Decimal('18.00'),
                        'fulfillment_mode': 'FRANCHISE_FULFILLED',
                        'vendor': vendor,
                        'franchise_store': store,
                        'item_status': 'DELIVERED',
                    },
                )

                VendorEarning.objects.get_or_create(
                    vendor=vendor,
                    order=order,
                    defaults={
                        'gross_amount': total_price,
                        'commission_percentage': Decimal('12.00'),
                        'commission_amount': (total_price * Decimal('0.12')).quantize(Decimal('0.01')),
                        'net_amount': (total_price * Decimal('0.88')).quantize(Decimal('0.01')),
                        'status': 'PAID',
                        'payout_date': ordered_at + timedelta(days=2),
                    },
                )

                FranchiseStoreEarning.objects.get_or_create(
                    store=store,
                    order=order,
                    defaults={
                        'order_amount': total_price,
                        'commission_percentage': Decimal('6.50'),
                        'commission_amount': (total_price * Decimal('0.065')).quantize(Decimal('0.01')),
                        'earning_type': 'FULFILLMENT',
                        'status': 'CREDITED',
                        'credited_at': ordered_at + timedelta(days=1),
                    },
                )
                order_count += 1

        now = timezone.now()
        telemetry_rows = []
        tracked_users = [admin_user] + customers
        for day_back in range(days, 0, -1):
            point = now - timedelta(days=day_back)
            for user in tracked_users:
                sid = f'session-{user.mobile}-{day_back}'
                telemetry_rows.extend([
                    {
                        'event_type': 'page_view',
                        'timestamp': point,
                        'session': sid,
                        'device': 'android',
                        'page': '/dashboard',
                        'metadata': {'source': 'seed'},
                        'client_event_id': f'pv-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'recommendation_impression',
                        'timestamp': point + timedelta(minutes=1),
                        'session': sid,
                        'device': 'android',
                        'page': '/dashboard',
                        'metadata': {'slot': 'hero'},
                        'client_event_id': f'ri-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'recommendation_click',
                        'timestamp': point + timedelta(minutes=2),
                        'session': sid,
                        'device': 'android',
                        'page': '/dashboard',
                        'metadata': {'slot': 'hero'},
                        'client_event_id': f'rc-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'marketplace_product_click',
                        'timestamp': point + timedelta(minutes=4),
                        'session': sid,
                        'device': 'android',
                        'page': '/marketplace',
                        'metadata': {'product_slug': products[(day_back + len(user.mobile)) % len(products)].slug},
                        'client_event_id': f'mpc-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'checkout_start',
                        'timestamp': point + timedelta(minutes=5),
                        'session': sid,
                        'device': 'android',
                        'page': '/checkout',
                        'metadata': {'cart_value': 999},
                        'client_event_id': f'cs-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'checkout_complete',
                        'timestamp': point + timedelta(minutes=6),
                        'session': sid,
                        'device': 'android',
                        'page': '/checkout/success',
                        'metadata': {'order_value': 999},
                        'client_event_id': f'cc-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'wallet_usage',
                        'timestamp': point + timedelta(minutes=7),
                        'session': sid,
                        'device': 'android',
                        'page': '/wallet',
                        'metadata': {'wallet': 'main_wallet', 'amount': 150},
                        'client_event_id': f'wu-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'reorder_click',
                        'timestamp': point + timedelta(minutes=8),
                        'session': sid,
                        'device': 'android',
                        'page': '/orders',
                        'metadata': {'source': 'order_history'},
                        'client_event_id': f'ro-{user.mobile}-{day_back}',
                    },
                    {
                        'event_type': 'api_timing',
                        'timestamp': point + timedelta(minutes=10),
                        'session': sid,
                        'device': 'android',
                        'page': '/api/orders',
                        'metadata': {'status': '200', 'durationMs': 280},
                        'client_event_id': f'api-ok-{user.mobile}-{day_back}',
                    },
                ])

        # Add concentrated operational spikes for anomaly validation in the last hour.
        for i in range(30):
            telemetry_rows.append(
                {
                    'event_type': 'api_timing',
                    'timestamp': now - timedelta(minutes=i),
                    'session': f'ops-spike-{i}',
                    'device': 'web',
                    'page': '/api/orders',
                    'metadata': {'status': '500', 'durationMs': 1700},
                    'client_event_id': f'ops-fail-{i}',
                }
            )
        for i in range(14):
            telemetry_rows.append(
                {
                    'event_type': 'notification_delivery_failure',
                    'timestamp': now - timedelta(minutes=i * 2),
                    'session': f'notif-spike-{i}',
                    'device': 'web',
                    'page': '/notifications',
                    'metadata': {'provider': 'fcm'},
                    'client_event_id': f'notif-fail-{i}',
                }
            )

        from apps.telemetry.services import ingest_events  # local import to avoid circulars on startup

        for user in tracked_users:
            user_events = [r for r in telemetry_rows if f'-{user.mobile}-' in r['client_event_id']]
            if user_events:
                ingest_events(user, user_events, source='seed')

        ingest_events(admin_user, [r for r in telemetry_rows if r['client_event_id'].startswith('ops-')], source='seed')
        ingest_events(admin_user, [r for r in telemetry_rows if r['client_event_id'].startswith('notif-')], source='seed')

        aggregate_kpis('DAY')
        aggregate_kpis('WEEK')
        aggregate_kpis('MONTH')
        compute_cohort_snapshots()
        compute_retention_snapshots(max_days=30)
        compute_funnel_snapshots()
        detect_anomalies()

        self.stdout.write(self.style.SUCCESS('E2E seed completed successfully.'))
        self.stdout.write(
            self.style.SUCCESS(
                f'Admin mobile: {admin_mobile} | customers: {len(customers)} | products: {len(products)} | orders processed: {order_count}'
            )
        )
