from __future__ import annotations

from django.core.management.base import BaseCommand, CommandError
from django.contrib.sites.models import Site

from orgs.models import Organization, OrganizationSite


class Command(BaseCommand):
    help = "Create or update a mapping between a Django Site domain and an Organization."

    def add_arguments(self, parser):
        parser.add_argument("--domain", required=True, help="Site domain (e.g., c1.lvh.me)")
        parser.add_argument(
            "--org",
            required=True,
            help="Organization identifier: code (preferred) or numeric ID",
        )
        parser.add_argument(
            "--site-name",
            default=None,
            help="Optional display name for the Site; used when creating it",
        )
        parser.add_argument(
            "--create-site",
            action="store_true",
            help="Create the Site if it does not exist",
        )
        parser.add_argument(
            "--update",
            action="store_true",
            help="Update existing mapping to point to the given Organization",
        )
        parser.add_argument(
            "--create-org",
            action="store_true",
            help="Create the Organization if it does not exist (uses --org as code)",
        )
        parser.add_argument(
            "--org-name",
            default=None,
            help="Optional Organization name to use when creating (defaults to code)",
        )

    def handle(self, *args, **options):
        # argparse stores values under the dest name (no leading dashes)
        domain: str = options["domain"]
        org_ident: str = options["org"]
        site_name: str | None = options.get("site_name")
        create_site: bool = bool(options.get("create_site", False))
        update: bool = bool(options.get("update", False))
        create_org: bool = bool(options.get("create_org", False))
        org_name: str | None = options.get("org_name")

        # Load organization by code or id
        org = None
        if org_ident.isdigit():
            org = Organization.objects.filter(pk=int(org_ident)).first()
        if org is None:
            org = Organization.objects.filter(code=org_ident).first() or Organization.objects.filter(name=org_ident).first()
        if org is None:
            if create_org and not org_ident.isdigit():
                org = Organization.objects.create(code=org_ident, name=org_name or org_ident)
                self.stdout.write(self.style.SUCCESS(f"Created Organization: id={org.id} code={org.code} name={org.name}"))
            else:
                raise CommandError(f"Organization not found by code/id/name: {org_ident}")

        # Load or create the Site
        site = Site.objects.filter(domain__iexact=domain).first()
        if site is None:
            if not create_site:
                raise CommandError(
                    f"Site with domain '{domain}' not found. Use --create-site to create it."
                )
            site = Site.objects.create(domain=domain, name=site_name or domain)
            self.stdout.write(self.style.SUCCESS(f"Created Site: id={site.id} domain={site.domain}"))
        elif site_name and site.name != site_name:
            site.name = site_name
            site.save(update_fields=["name"])
            self.stdout.write(self.style.SUCCESS(f"Updated Site name: id={site.id} name={site.name}"))

        # Create or update mapping
        mapping = OrganizationSite.objects.filter(site=site).first()
        if mapping is None:
            OrganizationSite.objects.create(site=site, organization=org)
            self.stdout.write(
                self.style.SUCCESS(
                    f"Created OrganizationSite: site={site.domain} -> org={org.code} ({org.id})"
                )
            )
        else:
            if mapping.organization_id == org.id:
                self.stdout.write(
                    self.style.WARNING(
                        f"Mapping already exists: site={site.domain} -> org={org.code} ({org.id})"
                    )
                )
            else:
                if not update:
                    raise CommandError(
                        f"Site {site.domain} already mapped to org {mapping.organization.code}. Use --update to change."
                    )
                mapping.organization = org
                mapping.save(update_fields=["organization"])
                self.stdout.write(
                    self.style.SUCCESS(
                        f"Updated OrganizationSite: site={site.domain} -> org={org.code} ({org.id})"
                    )
                )

        self.stdout.write(self.style.SUCCESS("Done."))
