"""Kategori iş mantığı — CRUD, slug benzersizliği, parent doğrulama."""
from fastapi import Depends

from app.models.product import ProductCategory
from app.repositories.category_repo import CategoryRepository
from app.schemas.product import (
    CategoryResponse,
    CreateCategoryRequest,
    UpdateCategoryRequest,
)
from app.utils.exceptions import ConflictError, NotFoundError, ValidationError


class CategoryService:
    def __init__(self, repo: CategoryRepository = Depends()):
        self.repo = repo

    async def list_categories(self, tenant_id: str) -> list[dict]:
        cats = await self.repo.list_by_tenant(tenant_id)
        return [CategoryResponse.model_validate(c).model_dump(mode="json") for c in cats]

    async def create_category(
        self, tenant_id: str, body: CreateCategoryRequest
    ) -> CategoryResponse:
        if await self.repo.slug_exists(tenant_id, body.slug):
            raise ConflictError("Bu slug zaten kullanılıyor.")
        await self._validate_parent(tenant_id, body.parent_id)
        cat = await self.repo.create(tenant_id=tenant_id, **body.model_dump())
        return CategoryResponse.model_validate(cat)

    async def update_category(
        self, category_id: str, tenant_id: str, body: UpdateCategoryRequest
    ) -> CategoryResponse:
        cat = await self._get_or_404(category_id, tenant_id)
        updates = body.model_dump(exclude_none=True)

        if "slug" in updates and await self.repo.slug_exists(
            tenant_id, updates["slug"], exclude_id=category_id
        ):
            raise ConflictError("Bu slug zaten kullanılıyor.")
        if "parent_id" in updates:
            if updates["parent_id"] == category_id:
                raise ValidationError("Kategori kendi üst kategorisi olamaz.")
            await self._validate_parent(tenant_id, updates["parent_id"])

        cat = await self.repo.update(cat, **updates)
        return CategoryResponse.model_validate(cat)

    async def delete_category(self, category_id: str, tenant_id: str) -> None:
        cat = await self._get_or_404(category_id, tenant_id)
        await self.repo.delete(cat)

    async def _get_or_404(self, category_id: str, tenant_id: str) -> ProductCategory:
        cat = await self.repo.get(category_id, tenant_id)
        if not cat:
            raise NotFoundError("Kategori")
        return cat

    async def _validate_parent(self, tenant_id: str, parent_id: str | None) -> None:
        if parent_id and not await self.repo.get(parent_id, tenant_id):
            raise ValidationError("Üst kategori bulunamadı.")
