"""سرویس Onboarding: ایجاد و فعال‌سازی tenant توسط کاربر جاری.

جریان کامل:
    ۱. POST /onboarding/tenant           → ایجاد tenant (status=pending_activation) + عضویت owner + پلن پیش‌فرض + زیردامنه خودکار
    ۲. PATCH /onboarding/tenant/{id}/branding → تنظیم رنگ/لوگو
    ۳. PATCH /onboarding/tenant/{id}/domain   → افزودن دامنه اختصاصی (اختیاری)
    ۴. POST /onboarding/tenant/{id}/complete  → اعتبارسنجی و فعال‌سازی نهایی (status=active)
"""
from __future__ import annotations

from uuid import UUID

from sqlalchemy.ext.asyncio import AsyncSession

from app.core.config import settings
from app.models.domain import Domain
from app.models.enums import DomainType, DomainVerificationStatus, TenantStatus
from app.models.tenant import Tenant
from app.models.user import User
from app.repositories.tenant import DomainRepository, TenantRepository
from app.schemas.onboarding import (
    OnboardingBrandingUpdate,
    OnboardingDomainUpdate,
    OnboardingTenantCreate,
)
from app.schemas.tenant import TenantCreate
from app.services.event_service import EventService
from app.services.membership_service import MembershipService
from app.services.ssl_provision import enqueue_domain_ssl
from app.services.tenant_service import TenantService
from shared.events import CoreEventType
from shared.exceptions import ConflictError, ValidationAppError


class OnboardingService:
    def __init__(self, session: AsyncSession) -> None:
        self.session = session
        self.tenant_service = TenantService(session)
        self.tenant_repo = TenantRepository(session)
        self.domain_repo = DomainRepository(session)
        self.membership_service = MembershipService(session)
        self.events = EventService(session)

    async def create_tenant(self, core_user: User, data: OnboardingTenantCreate) -> Tenant:
        tenant = await self.tenant_service.create(
            TenantCreate(
                name=data.business_name,
                slug=data.slug,
                owner_user_id=core_user.id,
            )
        )

        tenant.status = TenantStatus.PENDING_ACTIVATION
        tenant.business_type = data.business_type
        tenant.default_locale = data.default_locale
        tenant.timezone = data.timezone
        await self.session.commit()
        await self.session.refresh(tenant)

        await self.membership_service.create_owner_membership(tenant.id, core_user.id)

        # Commercial Runtime owns plans/subscriptions — FE activates via
        # POST /api/v1/commercial/subscriptions (bundle/plan/pricing from registry).
        # No legacy FREE/STARTER plan assignment.

        await self._create_default_subdomain(tenant)

        if core_user.current_tenant_id is None:
            core_user.current_tenant_id = tenant.id
            await self.session.commit()

        await self.session.refresh(tenant)
        return tenant

    async def _create_default_subdomain(self, tenant: Tenant) -> None:
        base_domain = (settings.platform_base_domain or "").strip().lower()
        if not base_domain:
            return
        host = f"{tenant.slug}.{base_domain}"
        if await self.domain_repo.domain_exists(host):
            return
        domain = Domain(
            tenant_id=tenant.id,
            domain=host,
            domain_type=DomainType.SUBDOMAIN,
            is_primary=True,
            is_verified=True,
            verification_status=DomainVerificationStatus.VERIFIED,
        )
        await self.domain_repo.add(domain)
        await self.events.record(
            event_type=CoreEventType.DOMAIN_CREATED.value,
            aggregate_type="domain",
            aggregate_id=str(domain.id),
            tenant_id=tenant.id,
            payload={"domain": host, "type": "subdomain", "auto_assigned": True},
        )
        await self.session.commit()
        enqueue_domain_ssl(host)

    async def update_branding(
        self, tenant_id: UUID, data: OnboardingBrandingUpdate
    ) -> Tenant:
        tenant = await self.tenant_service.get(tenant_id)
        if data.primary_color is not None:
            tenant.primary_color = data.primary_color
        if data.secondary_color is not None:
            tenant.secondary_color = data.secondary_color
        if data.logo_url is not None:
            tenant.logo_url = data.logo_url
        if data.favicon_url is not None:
            tenant.favicon_url = data.favicon_url
        await self.session.commit()
        await self.session.refresh(tenant)
        return tenant

    async def update_domain(self, tenant_id: UUID, data: OnboardingDomainUpdate) -> Tenant:
        tenant = await self.tenant_service.get(tenant_id)
        if data.custom_domain:
            if await self.domain_repo.domain_exists(data.custom_domain):
                raise ConflictError(
                    f"دامنه تکراری است: {data.custom_domain}", error_code="domain_taken"
                )
            domain = Domain(
                tenant_id=tenant.id,
                domain=data.custom_domain,
                domain_type=DomainType.CUSTOM_DOMAIN,
                is_primary=False,
                is_verified=False,
                verification_status=DomainVerificationStatus.PENDING,
            )
            await self.domain_repo.add(domain)
            await self.events.record(
                event_type=CoreEventType.DOMAIN_CREATED.value,
                aggregate_type="domain",
                aggregate_id=str(domain.id),
                tenant_id=tenant.id,
                payload={"domain": data.custom_domain, "type": "custom"},
            )
            await self.session.commit()
            # فقط اگر DNS از قبل به nginx اشاره کند certbot موفق می‌شود
            enqueue_domain_ssl(data.custom_domain)
        await self.session.refresh(tenant)
        return tenant

    async def complete(self, tenant_id: UUID) -> Tenant:
        tenant = await self.tenant_service.get(tenant_id)

        if not tenant.name or not tenant.slug:
            raise ValidationAppError(
                "اطلاعات کسب‌وکار (نام/slug) تکمیل نشده است", error_code="onboarding_incomplete"
            )

        owners = await self.membership_service.count_active_owners(tenant_id)
        if owners < 1:
            raise ValidationAppError(
                "tenant باید حداقل یک مالک فعال داشته باشد", error_code="owner_required"
            )

        tenant.onboarding_completed = True
        tenant.status = TenantStatus.ACTIVE
        await self.events.record(
            event_type=CoreEventType.TENANT_ACTIVATED.value,
            aggregate_type="tenant",
            aggregate_id=str(tenant.id),
            tenant_id=tenant.id,
            payload={"onboarding_completed": True},
        )
        await self.session.commit()
        await self.session.refresh(tenant)
        await self.tenant_service._invalidate_cache(tenant.id)
        return tenant
