"""
Service per la gestione dei template messaggi (Feature 1).
"""

import uuid

from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.exceptions import ConflictError, NotFoundError
from app.models.template import MessageTemplate
from app.schemas.template import TemplateCreate, TemplateUpdate


class TemplateService:
    def __init__(self, db: AsyncSession):
        self.db = db

    async def list_templates(
        self,
        tenant_id: uuid.UUID,
        q: str | None = None,
    ) -> tuple[list[MessageTemplate], int]:
        query = select(MessageTemplate).where(MessageTemplate.tenant_id == tenant_id)
        if q:
            query = query.where(MessageTemplate.name.ilike(f"%{q}%"))
        query = query.order_by(MessageTemplate.name)

        count_q = select(func.count()).select_from(query.subquery())
        total = (await self.db.execute(count_q)).scalar_one()
        items = list((await self.db.execute(query)).scalars().all())
        return items, total

    async def get_template(
        self, tenant_id: uuid.UUID, template_id: uuid.UUID
    ) -> MessageTemplate:
        result = await self.db.execute(
            select(MessageTemplate).where(
                MessageTemplate.id == template_id,
                MessageTemplate.tenant_id == tenant_id,
            )
        )
        template = result.scalar_one_or_none()
        if not template:
            raise NotFoundError(f"Template {template_id} non trovato")
        return template

    async def create_template(
        self,
        tenant_id: uuid.UUID,
        data: TemplateCreate,
        created_by: uuid.UUID | None = None,
    ) -> MessageTemplate:
        # Verifica unicita' nome
        existing = await self.db.execute(
            select(MessageTemplate).where(
                MessageTemplate.tenant_id == tenant_id,
                MessageTemplate.name == data.name,
            )
        )
        if existing.scalar_one_or_none():
            raise ConflictError(f"Template '{data.name}' gia' esistente")

        template = MessageTemplate(
            tenant_id=tenant_id,
            name=data.name,
            description=data.description,
            subject=data.subject,
            body_text=data.body_text,
            body_html=data.body_html,
            created_by=created_by,
        )
        self.db.add(template)
        await self.db.commit()
        await self.db.refresh(template)
        return template

    async def update_template(
        self,
        tenant_id: uuid.UUID,
        template_id: uuid.UUID,
        data: TemplateUpdate,
    ) -> MessageTemplate:
        template = await self.get_template(tenant_id, template_id)

        if data.name is not None:
            existing = await self.db.execute(
                select(MessageTemplate).where(
                    MessageTemplate.tenant_id == tenant_id,
                    MessageTemplate.name == data.name,
                    MessageTemplate.id != template_id,
                )
            )
            if existing.scalar_one_or_none():
                raise ConflictError(f"Template '{data.name}' gia' esistente")
            template.name = data.name

        if data.description is not None:
            template.description = data.description
        if data.subject is not None:
            template.subject = data.subject
        if data.body_text is not None:
            template.body_text = data.body_text
        if data.body_html is not None:
            template.body_html = data.body_html

        await self.db.commit()
        await self.db.refresh(template)
        return template

    async def delete_template(
        self, tenant_id: uuid.UUID, template_id: uuid.UUID
    ) -> None:
        template = await self.get_template(tenant_id, template_id)
        await self.db.delete(template)
        await self.db.commit()
