# app/modules/tenancy/services/store_subdomain_service.py
"""
Service for managing StorePlatform custom subdomains.

Handles validation (format, uniqueness) and CRUD operations on
the custom_subdomain field of StorePlatform entries.
"""

import logging
import re

from sqlalchemy import func
from sqlalchemy.orm import Session

from app.exceptions.base import (
    ConflictException,
    ResourceNotFoundException,
    ValidationException,
)
from app.modules.tenancy.models import Platform, Store
from app.modules.tenancy.models.store_platform import StorePlatform

logger = logging.getLogger(__name__)

# Subdomain rules: lowercase alphanumeric + hyphens, 3-63 chars, no leading/trailing hyphen
_SUBDOMAIN_RE = re.compile(r"^[a-z0-9]([a-z0-9-]{1,61}[a-z0-9])?$")


class StoreSubdomainService:
    """Manage custom subdomains on StorePlatform entries."""

    def get_custom_subdomains(self, db: Session, store_id: int) -> list[dict]:
        """
        List all platform memberships for a store with their custom subdomains.

        Returns a list of dicts with platform info and custom_subdomain (may be None).
        """
        store = db.query(Store).filter(Store.id == store_id).first()
        if not store:
            raise ResourceNotFoundException("Store", str(store_id))

        memberships = (
            db.query(StorePlatform)
            .filter(
                StorePlatform.store_id == store_id,
                StorePlatform.is_active.is_(True),
            )
            .all()
        )

        results = []
        for sp in memberships:
            platform = db.query(Platform).filter(Platform.id == sp.platform_id).first()
            if not platform:
                continue
            results.append({
                "store_platform_id": sp.id,
                "platform_id": sp.platform_id,
                "platform_code": platform.code,
                "platform_name": platform.name,
                "platform_domain": platform.domain,
                "custom_subdomain": sp.custom_subdomain,
                "default_subdomain": store.subdomain,
                "full_url": (
                    f"{sp.custom_subdomain}.{platform.domain}"
                    if sp.custom_subdomain and platform.domain
                    else None
                ),
                "default_url": (
                    f"{store.subdomain}.{platform.domain}"
                    if store.subdomain and platform.domain
                    else None
                ),
            })

        return results

    def set_custom_subdomain(
        self, db: Session, store_id: int, platform_id: int, subdomain: str
    ) -> StorePlatform:
        """
        Set or update the custom_subdomain for a store on a specific platform.

        Validates:
        - Subdomain format (lowercase, alphanumeric + hyphens)
        - Uniqueness on the platform (no other store claims it)
        - StorePlatform membership exists and is active
        """
        subdomain = subdomain.strip().lower()

        # Validate format
        if not _SUBDOMAIN_RE.match(subdomain):
            raise ValidationException(
                "Must be 3-63 characters, lowercase alphanumeric and hyphens, "
                "cannot start or end with a hyphen.",
                field="custom_subdomain",
            )

        # Find the membership
        sp = (
            db.query(StorePlatform)
            .filter(
                StorePlatform.store_id == store_id,
                StorePlatform.platform_id == platform_id,
                StorePlatform.is_active.is_(True),
            )
            .first()
        )
        if not sp:
            raise ResourceNotFoundException(
                "StorePlatform",
                f"store_id={store_id}, platform_id={platform_id}",
            )

        # Check uniqueness on this platform (exclude current entry)
        existing = (
            db.query(StorePlatform)
            .filter(
                func.lower(StorePlatform.custom_subdomain) == subdomain,
                StorePlatform.platform_id == platform_id,
                StorePlatform.id != sp.id,
            )
            .first()
        )
        if existing:
            raise ConflictException(
                f"Subdomain '{subdomain}' is already claimed by another store "
                f"on this platform."
            )

        sp.custom_subdomain = subdomain
        db.flush()

        logger.info(
            f"Set custom_subdomain='{subdomain}' for store_id={store_id} "
            f"on platform_id={platform_id}"
        )
        return sp

    def clear_custom_subdomain(
        self, db: Session, store_id: int, platform_id: int
    ) -> StorePlatform:
        """Clear the custom_subdomain for a store on a specific platform."""
        sp = (
            db.query(StorePlatform)
            .filter(
                StorePlatform.store_id == store_id,
                StorePlatform.platform_id == platform_id,
                StorePlatform.is_active.is_(True),
            )
            .first()
        )
        if not sp:
            raise ResourceNotFoundException(
                "StorePlatform",
                f"store_id={store_id}, platform_id={platform_id}",
            )

        old_value = sp.custom_subdomain
        sp.custom_subdomain = None
        db.flush()

        logger.info(
            f"Cleared custom_subdomain (was '{old_value}') for store_id={store_id} "
            f"on platform_id={platform_id}"
        )
        return sp


store_subdomain_service = StoreSubdomainService()
