from pathlib import Path

import yaml
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError

from shared_auth.conf import get_setting


class Command(BaseCommand):
    help = "Generate permissions from permissions.yml"

    def add_arguments(self, parser):
        parser.add_argument(
            "--file",
            default="permissions.yml",
            help="Path to permissions YAML file (default: permissions.yml)",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Show what would be done without making changes",
        )

    def handle(self, *args, **options):
        from shared_auth.utils import get_permission_model, get_system_model

        system_id = get_setting("SYSTEM_ID", None)
        if not system_id:
            raise CommandError("SYSTEM_ID not configured in settings.")

        System = get_system_model()
        try:
            system = System.objects.using("auth_db").get(id=system_id)
        except System.DoesNotExist:
            raise CommandError(f"System with ID {system_id} not found.")

        self.stdout.write(f"System: {system.name} (ID: {system_id})")

        # Find and parse YAML
        yaml_path = self._find_yaml(options["file"])
        if not yaml_path:
            raise CommandError(f"File not found: {options['file']}")

        with open(yaml_path, encoding="utf-8") as f:
            data = yaml.safe_load(f)

        scopes = data.get("permissions", {}).get("scopes", {})
        if not scopes:
            raise CommandError("No scopes found in YAML file.")

        Permission = get_permission_model()
        dry_run = options["dry_run"]
        created, updated = 0, 0

        for scope, perms in scopes.items():
            self.stdout.write(f"\n[{scope}]")

            for p in perms:
                codename = p.get("codename")
                name = p.get("name")
                description = p.get("description", "")

                if not codename or not name:
                    continue

                defaults = {"name": name, "description": description, "scope": scope}

                if dry_run:
                    exists = (
                        Permission.objects.using("auth_db")
                        .filter(codename=codename, system_id=system_id)
                        .exists()
                    )
                    status = "exists" if exists else "new"
                    self.stdout.write(f"  [{status}] {codename}")
                else:
                    obj, is_new = Permission.objects.using("auth_db").update_or_create(
                        codename=codename,
                        system_id=system_id,
                        defaults=defaults,
                    )
                    if is_new:
                        created += 1
                        self.stdout.write(self.style.SUCCESS(f"  + {codename}"))
                    else:
                        updated += 1
                        self.stdout.write(f"  ~ {codename}")

        self.stdout.write(f"\nCreated: {created} | Updated: {updated}")

    def _find_yaml(self, file_path: str) -> Path | None:
        paths = [
            Path(file_path),
            Path(settings.BASE_DIR) / file_path
            if hasattr(settings, "BASE_DIR")
            else None,
            Path.cwd() / file_path,
        ]
        for p in paths:
            if p and p.exists():
                return p
        return None
