import datetime
from typing import Literal

import jwt
from pydantic import BaseModel, Field, field_validator

from src.huesoporro.settings import Settings


class TwitchAuth(BaseModel):
    access_token: str
    refresh_token: str
    userinfo: dict


class ExternalAuth(BaseModel):
    credentials: dict
    type: Literal["twitch"] = "twitch"


class User(BaseModel):
    user: str
    external_auth: dict[Literal["twitch", "discord"], dict]

    def encode(
        self, settings: Settings | None = None, exclude_fields: set[str] | None = None
    ) -> str:
        s = settings or Settings.get()
        exclude_fields = exclude_fields or {"external_auth"}
        return jwt.encode(
            self.model_dump(exclude=exclude_fields),
            key=s.jwt_secret.get_secret_value(),
            algorithm="HS256",
        )

    @classmethod
    def decode(cls, token: str, settings: Settings | None = None) -> dict:
        s = settings or Settings.get()
        return jwt.decode(
            token, key=s.jwt_secret.get_secret_value(), algorithms=["HS256"]
        )

    @property
    def twitch_access_token(self):
        return self.external_auth["twitch"]["access_token"]


class ChatbotSettings(BaseModel):
    automatic_generation_timer: int = 300
    automatic_quote_timer: int = 500
    mods: list[str] = Field(default_factory=list)

    @property
    def mods_as_string(self):
        if not self.mods:
            return ""
        return ",".join(self.mods)

    @field_validator("mods", mode="before")
    @classmethod
    def format_mods_from_string(cls, v):
        if isinstance(v, str):
            return v.split(",")
        return v


class Sentence(BaseModel):
    id: int
    sentence: str
    created_at: float
    last_updated_at: float
    user: User


class Quote(BaseModel):
    quote: str
    author: User
    channel: User
    created_at: datetime.datetime
    last_updated_at: datetime.datetime

    def as_pretty(self) -> str:
        return f"«{self.quote}» - {self.author}"

    def as_pretty_saved(self):
        return f"He añadido la cita «{self.quote}» de {self.author}"
