from __future__ import annotations

import secrets

from django.core.management.base import BaseCommand

from accounts.models import User
from core.permissions import LEGACY_ROLE_MAP, Role
from finance.models import Account, ExpenseCategory
from inventory.models import Branch, StockLocation
from accounts.rbac import ensure_role_groups, sync_user_role_group


class Command(BaseCommand):
    help = (
        "Bootstrap system defaults: super admin, role normalization, "
        "locations, accounts, and expense categories."
    )

    def add_arguments(self, parser):
        parser.add_argument("--username", default="admin")
        parser.add_argument("--email", default="")
        parser.add_argument("--password", default="")
        parser.add_argument(
            "--normalize-legacy-roles",
            action="store_true",
            help="Normalize legacy roles (owner/manager/cashier) to new RBAC roles.",
        )
        parser.add_argument(
            "--seed-defaults",
            action="store_true",
            help="Create default stock locations, account, and expense categories.",
        )

    def handle(self, *args, **options):
        username = options["username"].strip()
        email = options["email"].strip()
        password = options["password"].strip()

        if not username:
            self.stderr.write(self.style.ERROR("--username is required."))
            return

        generated_password = ""
        if not password:
            generated_password = secrets.token_urlsafe(12)
            password = generated_password

        user, created = User.objects.get_or_create(
            username=username,
            defaults={
                "email": email,
                "role": Role.SUPER_ADMIN,
                "is_staff": True,
                "is_superuser": True,
                "is_active": True,
            },
        )

        changed = False
        if user.role != Role.SUPER_ADMIN:
            user.role = Role.SUPER_ADMIN
            changed = True
        if not user.is_staff:
            user.is_staff = True
            changed = True
        if not user.is_superuser:
            user.is_superuser = True
            changed = True
        if not user.is_active:
            user.is_active = True
            changed = True
        if email and user.email != email:
            user.email = email
            changed = True

        user.set_password(password)
        changed = True

        if changed:
            user.save()

        if created:
            self.stdout.write(self.style.SUCCESS(f"Created super admin user '{username}'."))
        else:
            self.stdout.write(self.style.SUCCESS(f"Updated super admin user '{username}'."))

        if generated_password:
            self.stdout.write(
                self.style.WARNING(
                    f"Generated password for '{username}': {generated_password}"
                )
            )

        if options["normalize_legacy_roles"]:
            normalized_count = 0
            for legacy_role, normalized_role in LEGACY_ROLE_MAP.items():
                users = User.objects.filter(role=legacy_role)
                normalized_count += users.count()
                users.update(role=normalized_role)
            self.stdout.write(
                self.style.SUCCESS(
                    f"Normalized {normalized_count} user(s) from legacy roles."
                )
            )

        ensure_role_groups()
        sync_user_role_group(user)

        if options["seed_defaults"]:
            self._seed_defaults()

        self.stdout.write(self.style.SUCCESS("Bootstrap complete."))

    def _seed_defaults(self):
        default_branch, _ = Branch.objects.get_or_create(
            name="Main Branch",
            defaults={"is_active": True},
        )
        locations = [
            ("Main Store", "MAIN"),
            ("Library Store", "LIB"),
            ("Kitchen Store", "KIT"),
            ("Lab Store", "LAB"),
        ]
        created_locations = 0
        for name, code in locations:
            _, created = StockLocation.objects.get_or_create(
                name=name,
                defaults={"branch": default_branch, "code": code, "is_active": True},
            )
            if created:
                created_locations += 1

        categories = [
            "Salaries",
            "Utilities",
            "Rent",
            "Maintenance",
            "Transport",
            "Supplies",
        ]
        created_categories = 0
        for name in categories:
            _, created = ExpenseCategory.objects.get_or_create(name=name)
            if created:
                created_categories += 1

        account, account_created = Account.objects.get_or_create(
            name="Cash Till",
            defaults={
                "account_type": Account.AccountType.CASH,
                "balance": 0,
                "is_active": True,
            },
        )

        self.stdout.write(
            self.style.SUCCESS(
                "Seeded defaults: "
                f"{created_locations} location(s), "
                f"{created_categories} expense categor(ies), "
                f"account={'created' if account_created else 'existing'} ({account.name})."
            )
        )
