from django.core.management.base import BaseCommand, CommandError
from django.db import transaction

from apps.accounts.models import User
from apps.business.distributor.models import DistributorID
from apps.business.distributor.services.distributor_service import create_distributor_id
from apps.business.distributor.services.distributor_service import generate_distributor_code, generate_global_position
from apps.business.power_stream.services.power_stream_service import process_power_stream_bonus


class Command(BaseCommand):
    help = "Seed deep referral chains under a user's distributor IDs for power stream testing."

    def add_arguments(self, parser):
        parser.add_argument('--mobile', default='8668192080', help='Target user mobile number.')
        parser.add_argument('--start-index', type=int, default=3, help='1-based distributor index to start seeding from.')
        parser.add_argument('--depth', type=int, default=10, help='Downline depth to seed for power stream levels.')

    def handle(self, *args, **options):
        mobile = options['mobile']
        start_index = max(1, int(options['start_index']))
        depth = max(1, int(options['depth']))

        target_user = User.objects.filter(mobile=mobile).first()
        if not target_user:
            raise CommandError(f"User with mobile '{mobile}' not found.")

        target_distributors = list(
            DistributorID.objects.filter(user=target_user, is_active=True)
            .select_related('product__opportunity_bundle')
            .order_by('global_position')
        )
        if len(target_distributors) < start_index:
            raise CommandError(
                f"User {mobile} has only {len(target_distributors)} active distributor IDs; cannot start from index {start_index}."
            )

        seeded_users = 0
        seeded_distributors = 0
        created_bonus_records = 0

        for dist_position, root_distributor in enumerate(target_distributors[start_index - 1:], start=start_index):
            result = self._seed_chain_for_root(
                root_distributor=root_distributor,
                target_mobile=mobile,
                dist_position=dist_position,
                depth=depth,
            )
            seeded_users += result['users']
            seeded_distributors += result['distributors']
            created_bonus_records += result['bonus_records']

            self.stdout.write(
                self.style.SUCCESS(
                    f"Seeded distributor #{dist_position} {root_distributor.distributor_code}: "
                    f"users={result['users']} distributors={result['distributors']} bonus_records={result['bonus_records']}"
                )
            )

        self.stdout.write(
            self.style.SUCCESS(
                f"Completed power stream seed for {mobile}. users={seeded_users} distributors={seeded_distributors} bonus_records={created_bonus_records}"
            )
        )

    def _seed_chain_for_root(self, *, root_distributor, target_mobile, dist_position, depth):
        users_created = 0
        distributors_created = 0
        bonus_records_created = 0

        with transaction.atomic():
            branch_a_user = self._build_user(target_mobile, dist_position, branch='A', level=0, referrer_user=root_distributor.user)
            branch_a = self._create_active_distributor(
                user=branch_a_user,
                product=root_distributor.product,
                sponsor_distributor=root_distributor,
            )
            users_created += 1
            distributors_created += 1

            branch_b_user = self._build_user(target_mobile, dist_position, branch='B', level=0, referrer_user=root_distributor.user)
            branch_b = self._create_active_distributor(
                user=branch_b_user,
                product=root_distributor.product,
                sponsor_distributor=root_distributor,
            )
            users_created += 1
            distributors_created += 1

            current_sponsor = branch_a
            for level in range(1, depth + 1):
                chain_user = self._build_user(target_mobile, dist_position, branch='C', level=level, referrer_user=current_sponsor.user)
                chain_dist = self._create_active_distributor(
                    user=chain_user,
                    product=root_distributor.product,
                    sponsor_distributor=current_sponsor,
                )
                bonus_records_created += len(process_power_stream_bonus(chain_dist))
                users_created += 1
                distributors_created += 1
                current_sponsor = chain_dist

        return {
            'users': users_created,
            'distributors': distributors_created,
            'bonus_records': bonus_records_created,
        }

    def _build_user(self, target_mobile, dist_position, branch, level, referrer_user=None):
        email = f"psseed.{target_mobile}.{dist_position}.{branch}.{level}@truewave.test"

        existing = User.objects.filter(email=email).first()
        if existing:
            return existing

        mobile = self._next_unique_mobile(target_mobile, dist_position, branch, level)

        return User.objects.create_user(
            email=email,
            mobile=mobile,
            password='SeedPass@123',
            login_pin='1234',
            first_name='PS',
            last_name=f"{target_mobile[-4:]}{dist_position}{branch}{level}",
            referred_by=referrer_user,
            is_active=True,
            is_mobile_verified=True,
            is_email_verified=True,
            role='USER',
        )

    def _next_unique_mobile(self, target_mobile, dist_position, branch, level):
        branch_offset_map = {'A': 11, 'B': 37, 'C': 59}
        branch_offset = branch_offset_map.get(branch, 83)
        base = 7000000000 + (int(target_mobile[-4:]) * 10000) + (dist_position * 100) + branch_offset + level

        candidate = base
        while True:
            if candidate > 9999999999:
                candidate = 7000000000 + (candidate % 1000000000)
            mobile = str(candidate)
            if not User.objects.filter(mobile=mobile).exists():
                return mobile
            candidate += 1

    def _create_active_distributor(self, *, user, product, sponsor_distributor):
        existing = DistributorID.objects.filter(user=user, product=product).first()
        if existing:
            updates = []
            if sponsor_distributor and existing.sponsor_distributor_id != sponsor_distributor.id:
                existing.sponsor_distributor = sponsor_distributor
                updates.append('sponsor_distributor')
            if not existing.is_active:
                existing.is_active = True
                updates.append('is_active')
            if updates:
                updates.append('updated_at')
                existing.save(update_fields=updates)
            return existing

        return create_distributor_id(
            user=user,
            product=product,
            sponsor_distributor=sponsor_distributor,
        )