import uuid
from typing import Any

from sqlalchemy.ext.asyncio import AsyncSession

from app.core.exceptions import NotFoundError
from app.models import BankCard, SupportTicket, User
from app.repositories import BankCardRepository, SupportRepository
from app.services.log_service import LogService, LogType


class SupportService:
    def __init__(self, session: AsyncSession) -> None:
        self.session = session
        self.tickets = SupportRepository(session)
        self.cards = BankCardRepository(session)
        self.logs = LogService(session)

    async def create_ticket(
        self, user: User, message: str, subject: str | None = None, attachment: str | None = None
    ) -> SupportTicket:
        ticket = await self.tickets.create(
            user_id=user.id, subject=subject, message=message, attachment=attachment
        )
        await self.logs.write(
            LogType.SUPPORT, "ticket_created", subject or message[:80], user_id=user.id
        )
        return ticket

    async def get(self, ticket_id: uuid.UUID) -> SupportTicket:
        ticket = await self.tickets.get(ticket_id)
        if not ticket:
            raise NotFoundError("ticket_not_found")
        return ticket

    async def search(self, page: int, size: int, **filters: Any) -> tuple[list[SupportTicket], int]:
        return await self.tickets.search(page, size, **filters)

    async def reply(self, ticket_id: uuid.UUID, message: str) -> SupportTicket:
        ticket = await self.get(ticket_id)
        ticket.reply = message
        ticket.status = "answered"
        await self.session.flush()
        await self.logs.write(
            LogType.SUPPORT, "ticket_answered", message[:80], user_id=ticket.user_id
        )
        return ticket

    async def close(self, ticket_id: uuid.UUID) -> SupportTicket:
        ticket = await self.get(ticket_id)
        ticket.status = "closed"
        await self.session.flush()
        return ticket

    # -- bank cards -------------------------------------------------
    async def add_card(
        self, user: User, image: str | None, card_number: str | None, title: str | None = None
    ) -> BankCard:
        return await self.cards.create(
            user_id=user.id, image=image, card_number=card_number, title=title
        )

    async def list_cards(self, user_id: uuid.UUID) -> list[BankCard]:
        return await self.cards.list_for_user(user_id)

    async def set_card_status(self, card_id: uuid.UUID, status: str) -> BankCard:
        card = await self.cards.get(card_id)
        if not card:
            raise NotFoundError("card_not_found")
        card.status = status
        await self.session.flush()
        return card
