"""X (Twitter) account repository — typed CRUD via BaseRepository.

All persistence is delegated to :class:`BaseRepository` methods — no raw
SQL or SQLAlchemy imports.  Account-specific hooks (logging) are kept here.
"""

from __future__ import annotations

import logging
import uuid
from typing import Any

from repo_core import BaseRepository, hook
from repo_core.domains.x.account.model import XAccount

logger = logging.getLogger(__name__)


class XAccountRepository(BaseRepository[XAccount]):
    """CRUD for ``x_accounts`` via BaseRepository backends.

    Usage::

        repo = XAccountRepository(model=XAccount)
        async with repo:
            account = await repo.create_account({...})
            results = await repo.list_all(20, 0)
    """

    TABLE = "x_accounts"

    # -- Hooks -------------------------------------------------------------

    @hook("after_create")
    async def _log_create(self, account: XAccount) -> None:
        logger.debug("X account created: id=%s username=%s", account.id, account.username)

    @hook("after_update")
    async def _log_update(self, account: XAccount) -> None:
        logger.debug("X account updated: id=%s", account.id)

    @hook("after_delete")
    async def _log_delete(self, account: XAccount) -> None:
        logger.debug("X account deleted: id=%s", account.id)

    # -- CRUD --------------------------------------------------------------

    async def create_account(self, data: dict[str, Any]) -> XAccount:
        """Insert a new row and return the domain-model instance."""
        await self.emit("before_create", data)
        created = await self.insert_one(self.TABLE, data, returning=["*"])
        await self.emit("after_create", created)
        return created

    async def get_by_id(self, account_id: uuid.UUID) -> XAccount | None:
        return await self.find_by_id(self.TABLE, account_id)

    async def list_all(
        self, limit: int, offset: int
    ) -> tuple[list[XAccount], int]:
        total = await self.count(self.TABLE)
        rows = await self.all(
            self.TABLE,
            limit=limit,
            offset=offset,
            order_by=["-created_at"],
        )
        return rows, total

    async def find_by_username(self, username: str) -> XAccount | None:
        return await self.first(self.TABLE, {"username": username})

    async def find_by_email(self, email: str) -> XAccount | None:
        return await self.first(self.TABLE, {"email": email})

    async def find_by_mobile(self, mobile: str) -> XAccount | None:
        return await self.first(self.TABLE, {"mobile": mobile})

    async def find_by_account_id(self, account_id: str) -> XAccount | None:
        return await self.first(self.TABLE, {"account_id": account_id})

    async def find_by_status(
        self, status: str, limit: int = 20, offset: int = 0
    ) -> list[XAccount]:
        return await self.find(
            self.TABLE,
            {"status": status},
            limit=limit,
            offset=offset,
            order_by=["-created_at"],
        )

    async def find_by_proxy_region(
        self, proxy_region: str, limit: int = 20, offset: int = 0
    ) -> list[XAccount]:
        return await self.find(
            self.TABLE,
            {"proxy_region": proxy_region},
            limit=limit,
            offset=offset,
            order_by=["-created_at"],
        )

    async def delete_account(self, account_id: uuid.UUID) -> int:
        await self.emit("before_delete", account_id)
        result = await self.remove_by_id(self.TABLE, account_id)
        await self.emit("after_delete", account_id)
        return result

    async def set_status(
        self, account_id: uuid.UUID, status: str
    ) -> XAccount | None:
        updated = await self.update_by_id(
            self.TABLE, account_id, {"status": status}
        )
        if updated is not None:
            await self.emit("after_update", updated)
        return updated

    async def set_proxy_region(
        self, account_id: uuid.UUID, proxy_region: str
    ) -> XAccount | None:
        updated = await self.update_by_id(
            self.TABLE, account_id, {"proxy_region": proxy_region}
        )
        if updated is not None:
            await self.emit("after_update", updated)
        return updated
