import uuid
from typing import Any

from sqlalchemy import select

from app.models import BankCard, Log, Referral, Setting, SupportTicket
from app.repositories.base import BaseRepository


class SettingRepository(BaseRepository[Setting]):
    model = Setting

    async def get_by_key(self, key: str) -> Setting | None:
        return await self.get_by(key=key)

    async def all_settings(self, only_public: bool = False) -> list[Setting]:
        stmt = select(Setting).order_by(Setting.key)
        if only_public:
            stmt = stmt.where(Setting.is_public.is_(True))
        return list((await self.session.execute(stmt)).scalars().all())

    async def upsert(self, key: str, value: Any, title: str | None = None) -> Setting:
        setting = await self.get_by_key(key)
        if setting:
            setting.value = value
            if title:
                setting.title = title
            await self.session.flush()
            return setting
        return await self.create(key=key, value=value, title=title)


class LogRepository(BaseRepository[Log]):
    model = Log

    async def search(self, page: int, size: int, **filters: Any) -> tuple[list[Log], int]:
        stmt = select(Log).order_by(Log.created_at.desc())
        if filters.get("type"):
            stmt = stmt.where(Log.type == filters["type"])
        if filters.get("event"):
            stmt = stmt.where(Log.event == filters["event"])
        if filters.get("user_id"):
            stmt = stmt.where(Log.user_id == filters["user_id"])
        if filters.get("order_id"):
            stmt = stmt.where(Log.order_id == filters["order_id"])
        if filters.get("search"):
            stmt = stmt.where(Log.message.ilike(f"%{filters['search']}%"))
        return await self.paginate(stmt, page, size)


class ReferralRepository(BaseRepository[Referral]):
    model = Referral

    async def list_for_user(self, user_id: uuid.UUID, limit: int = 50) -> list[Referral]:
        stmt = (
            select(Referral)
            .where(Referral.referrer_user_id == user_id)
            .order_by(Referral.created_at.desc())
            .limit(limit)
        )
        return list((await self.session.execute(stmt)).scalars().all())

    async def search(self, page: int, size: int, **filters: Any) -> tuple[list[Referral], int]:
        stmt = select(Referral).order_by(Referral.created_at.desc())
        if filters.get("status"):
            stmt = stmt.where(Referral.status == filters["status"])
        return await self.paginate(stmt, page, size)


class SupportRepository(BaseRepository[SupportTicket]):
    model = SupportTicket

    async def search(self, page: int, size: int, **filters: Any) -> tuple[list[SupportTicket], int]:
        stmt = select(SupportTicket).order_by(SupportTicket.created_at.desc())
        if filters.get("status"):
            stmt = stmt.where(SupportTicket.status == filters["status"])
        if filters.get("user_id"):
            stmt = stmt.where(SupportTicket.user_id == filters["user_id"])
        return await self.paginate(stmt, page, size)


class BankCardRepository(BaseRepository[BankCard]):
    model = BankCard

    async def list_for_user(self, user_id: uuid.UUID) -> list[BankCard]:
        stmt = (
            select(BankCard)
            .where(BankCard.user_id == user_id)
            .order_by(BankCard.created_at.desc())
        )
        return list((await self.session.execute(stmt)).scalars().all())
