"""سرویس مدیریت و resolve دامنه‌ها."""
from __future__ import annotations

from typing import Sequence
from uuid import UUID

from sqlalchemy.ext.asyncio import AsyncSession

from app.models.domain import Domain
from app.repositories.tenant import DomainRepository, TenantRepository
from app.schemas.domain import DomainCreate
from app.services.event_service import EventService
from app.services.ssl_provision import enqueue_domain_ssl
from shared.events import CoreEventType
from shared.exceptions import ConflictError, NotFoundError


class DomainService:
    def __init__(self, session: AsyncSession) -> None:
        self.session = session
        self.repo = DomainRepository(session)
        self.tenant_repo = TenantRepository(session)
        self.events = EventService(session)

    async def create(self, tenant_id: UUID, data: DomainCreate) -> Domain:
        tenant = await self.tenant_repo.get(tenant_id)
        if tenant is None:
            raise NotFoundError(f"tenant یافت نشد: {tenant_id}")
        if await self.repo.domain_exists(data.domain):
            raise ConflictError(
                f"دامنه تکراری است: {data.domain}", error_code="domain_taken"
            )

        domain = Domain(
            tenant_id=tenant_id,
            domain=data.domain,
            domain_type=data.domain_type,
        )
        await self.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": domain.domain, "type": domain.domain_type.value},
        )
        await self.session.commit()
        await self.session.refresh(domain)
        enqueue_domain_ssl(domain.domain)
        return domain

    async def list_by_tenant(self, tenant_id: UUID) -> Sequence[Domain]:
        return await self.repo.list_by_tenant(tenant_id)

    async def resolve(self, domain: str) -> Domain:
        """یافتن دامنه و tenant متناظر آن."""
        found = await self.repo.get_by_domain(domain.strip().lower())
        if found is None:
            raise NotFoundError(f"دامنه یافت نشد: {domain}")
        return found
