import datetime
from contextlib import asynccontextmanager

import aiosqlite
from loguru import logger
from pydantic import BaseModel, Field

from src.huesoporro.models import ChatbotSettings, Sentence, User
from src.huesoporro.settings import Settings


class Database(BaseModel):
    s: Settings = Field(default_factory=Settings.get)

    @asynccontextmanager
    async def get_client(self, auto_commit=True):
        logger.info(f"Opening database connection: {self.s.db_filepath}")
        async with aiosqlite.connect(self.s.db_filepath) as db:
            yield db
            if auto_commit:
                await db.commit()

    @staticmethod
    def get_now() -> float:
        return datetime.datetime.now(datetime.UTC).timestamp()

    async def save_chatbot_settings(
        self, user: User, chatbot_settings: ChatbotSettings, auto_commit: bool = True
    ):
        async with self.get_client(auto_commit=auto_commit) as db:
            current_settings = await self.get_chatbot_settings(user)
            if current_settings:
                await db.execute(
                    """UPDATE settings SET
                automatic_generation_timer = ?,
                automatic_quote_timer = ?,
                mods = ?,
                last_updated_at = ?
                WHERE user_id = ?
                """,
                    (
                        chatbot_settings.automatic_generation_timer,
                        chatbot_settings.automatic_quote_timer,
                        chatbot_settings.mods_as_string,
                        self.get_now(),
                        user.user,
                    ),
                )
                return

            await db.execute(
                """INSERT INTO settings (
                user_id,
                automatic_generation_timer,
                automatic_quote_timer,
                mods,
                created_at,
                last_updated_at
            ) VALUES(?,?,?,?,?,?)
            """,
                (
                    user.user,
                    chatbot_settings.automatic_generation_timer,
                    chatbot_settings.automatic_quote_timer,
                    chatbot_settings.mods_as_string,
                    self.get_now(),
                    self.get_now(),
                ),
            )

    async def get_chatbot_settings(self, user: User) -> ChatbotSettings | None:
        async with self.get_client() as db:
            db.row_factory = aiosqlite.Row
            async with db.execute(
                "SELECT * FROM settings WHERE user_id = ?", (user.user,)
            ) as cursor:
                result = await cursor.fetchone()
        if not result:
            return None
        return ChatbotSettings(**dict(result))

    async def save_sentence(self, sentence: str, auto_commit=True):
        async with self.get_client(auto_commit=auto_commit) as db:
            await db.execute(
                "INSERT INTO sentences (sentence) VALUES (?)",
                (sentence,),
            )
            await db.commit()

    async def get_sentences(self, user: User) -> list[Sentence]:
        async with self.get_client() as db:
            db.row_factory = aiosqlite.Row
            async with db.execute(
                "SELECT * FROM sentences WHERE user_id = ?", (user.user,)
            ) as cursor:
                result = await cursor.fetchall()
            if not result:
                return []
            return [Sentence(user=user, **dict(value)) for value in result]
