# app/modules/tenancy/routes/api/admin_store_domains.py
"""
Admin endpoints for managing store custom domains.

Follows the architecture pattern:
- Endpoints only handle HTTP layer
- Business logic in service layer
- Domain exceptions bubble up to global handler
- Pydantic schemas for validation
"""

import logging

from fastapi import APIRouter, Body, Depends, Path
from sqlalchemy.orm import Session

from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.modules.tenancy.schemas.auth import UserContext
from app.modules.tenancy.schemas.store_domain import (
    DomainDeletionResponse,
    DomainVerificationInstructions,
    DomainVerificationResponse,
    StoreDomainCreate,
    StoreDomainListResponse,
    StoreDomainResponse,
    StoreDomainUpdate,
)
from app.modules.tenancy.services.store_domain_service import store_domain_service
from app.modules.tenancy.services.store_service import store_service

admin_store_domains_router = APIRouter(prefix="/stores")
logger = logging.getLogger(__name__)


@admin_store_domains_router.post("/{store_id}/domains", response_model=StoreDomainResponse)
def add_store_domain(
    store_id: int = Path(..., description="Store ID", gt=0),
    domain_data: StoreDomainCreate = Body(...),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Add a custom domain to store (Admin only).

    This endpoint:
    1. Validates the domain format
    2. Checks if domain is already registered
    3. Generates verification token
    4. Creates domain record (unverified, inactive)
    5. Returns domain with verification instructions

    **Domain Examples:**
    - myshop.com
    - shop.mybrand.com
    - customstore.net

    **Next Steps:**
    1. Store adds DNS TXT record
    2. Admin clicks "Verify Domain" to confirm ownership
    3. Once verified, domain can be activated

    **Raises:**
    - 404: Store not found
    - 409: Domain already registered
    - 422: Invalid domain format or reserved subdomain
    """
    domain = store_domain_service.add_domain(
        db=db, store_id=store_id, domain_data=domain_data
    )
    db.commit()

    return StoreDomainResponse(
        id=domain.id,
        store_id=domain.store_id,
        domain=domain.domain,
        is_primary=domain.is_primary,
        is_active=domain.is_active,
        is_verified=domain.is_verified,
        ssl_status=domain.ssl_status,
        platform_id=domain.platform_id,
        verification_token=domain.verification_token,
        verified_at=domain.verified_at,
        ssl_verified_at=domain.ssl_verified_at,
        created_at=domain.created_at,
        updated_at=domain.updated_at,
    )


@admin_store_domains_router.get("/{store_id}/domains", response_model=StoreDomainListResponse)
def list_store_domains(
    store_id: int = Path(..., description="Store ID", gt=0),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    List all domains for a store (Admin only).

    Returns domains ordered by:
    1. Primary domains first
    2. Creation date (newest first)

    **Raises:**
    - 404: Store not found
    """
    # Verify store exists (raises StoreNotFoundException if not found)
    store_service.get_store_by_id(db, store_id)

    domains = store_domain_service.get_store_domains(db, store_id)

    return StoreDomainListResponse(
        domains=[
            StoreDomainResponse(
                id=d.id,
                store_id=d.store_id,
                domain=d.domain,
                is_primary=d.is_primary,
                is_active=d.is_active,
                is_verified=d.is_verified,
                ssl_status=d.ssl_status,
                platform_id=d.platform_id,
                verification_token=d.verification_token if not d.is_verified else None,
                verified_at=d.verified_at,
                ssl_verified_at=d.ssl_verified_at,
                created_at=d.created_at,
                updated_at=d.updated_at,
            )
            for d in domains
        ],
        total=len(domains),
    )


@admin_store_domains_router.get("/domains/{domain_id}", response_model=StoreDomainResponse)
def get_domain_details(
    domain_id: int = Path(..., description="Domain ID", gt=0),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Get detailed information about a specific domain (Admin only).

    **Raises:**
    - 404: Domain not found
    """
    domain = store_domain_service.get_domain_by_id(db, domain_id)

    return StoreDomainResponse(
        id=domain.id,
        store_id=domain.store_id,
        domain=domain.domain,
        is_primary=domain.is_primary,
        is_active=domain.is_active,
        is_verified=domain.is_verified,
        ssl_status=domain.ssl_status,
        platform_id=domain.platform_id,
        verification_token=(
            domain.verification_token if not domain.is_verified else None
        ),
        verified_at=domain.verified_at,
        ssl_verified_at=domain.ssl_verified_at,
        created_at=domain.created_at,
        updated_at=domain.updated_at,
    )


@admin_store_domains_router.put("/domains/{domain_id}", response_model=StoreDomainResponse)
def update_store_domain(
    domain_id: int = Path(..., description="Domain ID", gt=0),
    domain_update: StoreDomainUpdate = Body(...),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Update domain settings (Admin only).

    **Can update:**
    - `is_primary`: Set as primary domain for store
    - `is_active`: Activate or deactivate domain

    **Important:**
    - Cannot activate unverified domains
    - Setting a domain as primary will unset other primary domains
    - Cannot modify domain name (delete and recreate instead)

    **Raises:**
    - 404: Domain not found
    - 400: Cannot activate unverified domain
    """
    domain = store_domain_service.update_domain(
        db=db, domain_id=domain_id, domain_update=domain_update
    )
    db.commit()

    return StoreDomainResponse(
        id=domain.id,
        store_id=domain.store_id,
        domain=domain.domain,
        is_primary=domain.is_primary,
        is_active=domain.is_active,
        is_verified=domain.is_verified,
        ssl_status=domain.ssl_status,
        platform_id=domain.platform_id,
        verification_token=None,  # Don't expose token after updates
        verified_at=domain.verified_at,
        ssl_verified_at=domain.ssl_verified_at,
        created_at=domain.created_at,
        updated_at=domain.updated_at,
    )


@admin_store_domains_router.delete("/domains/{domain_id}", response_model=DomainDeletionResponse)
def delete_store_domain(
    domain_id: int = Path(..., description="Domain ID", gt=0),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Delete a custom domain (Admin only).

    **Warning:** This is permanent and cannot be undone.

    **Raises:**
    - 404: Domain not found
    """
    # Get domain details before deletion
    domain = store_domain_service.get_domain_by_id(db, domain_id)
    store_id = domain.store_id
    domain_name = domain.domain

    # Delete domain
    message = store_domain_service.delete_domain(db, domain_id)
    db.commit()

    return DomainDeletionResponse(
        message=message, domain=domain_name, store_id=store_id
    )


@admin_store_domains_router.post("/domains/{domain_id}/verify", response_model=DomainVerificationResponse)
def verify_domain_ownership(
    domain_id: int = Path(..., description="Domain ID", gt=0),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Verify domain ownership via DNS TXT record (Admin only).

    **Verification Process:**
    1. Queries DNS for TXT record: `_orion-verify.{domain}`
    2. Checks if verification token matches
    3. If found, marks domain as verified

    **Requirements:**
    - Store must have added TXT record to their DNS
    - DNS propagation may take 5-15 minutes
    - Record format: `_orion-verify.domain.com` TXT `{token}`

    **After verification:**
    - Domain can be activated
    - Domain will be available for routing

    **Raises:**
    - 404: Domain not found
    - 400: Already verified, or verification failed
    - 502: DNS query failed
    """
    domain, message = store_domain_service.verify_domain(db, domain_id)
    db.commit()

    return DomainVerificationResponse(
        message=message,
        domain=domain.domain,
        verified_at=domain.verified_at,
        is_verified=domain.is_verified,
    )


@admin_store_domains_router.get(
    "/domains/{domain_id}/verification-instructions",
    response_model=DomainVerificationInstructions,
)
def get_domain_verification_instructions(
    domain_id: int = Path(..., description="Domain ID", gt=0),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Get DNS verification instructions for domain (Admin only).

    Returns step-by-step instructions for:
    1. Where to add DNS records
    2. What TXT record to create
    3. Links to common registrars
    4. Verification token

    **Use this endpoint to:**
    - Show stores how to verify their domain
    - Get the exact TXT record values
    - Access registrar links

    **Raises:**
    - 404: Domain not found
    """
    instructions = store_domain_service.get_verification_instructions(db, domain_id)

    return DomainVerificationInstructions(
        domain=instructions["domain"],
        verification_token=instructions["verification_token"],
        instructions=instructions["instructions"],
        txt_record=instructions["txt_record"],
        common_registrars=instructions["common_registrars"],
    )
