from pathlib import Path
from typing import ClassVar, Final, Optional, Any
from urllib.parse import urlparse, ParseResult

from aiogram.types import ChatAdministratorRights
from pydantic import field_validator, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """Улучшенный класс настроек с комплексной валидацией"""

    # Конфигурация загрузки переменных окружения
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
        case_sensitive=False,
        validate_default=True,
    )

    # Режимы и базовые параметры
    PYTHONUNBUFFERED: str = "1"
    LOCALE_PATH: str = "locales"

    DEBUG: bool = False
    OWNER: str = "@verdise"

    # Токены бота
    BOT_TOKEN: Optional[str] = None
    BOT_DEBUG_TOKEN: Optional[str] = None

    # Параметры сообщений
    PARSE_MODE: str = "HTML"
    ENCOD: str = "utf-8"
    TIME_FORMAT: str = "%Y-%m-%d %H:%M:%S"
    PREFIX: str = "/!.&?"
    BOT_LANGUAGE: str = "Aiogram3"

    # Настройки сообщений
    DISABLE_NOTIFICATION: bool = False
    PROTECT_CONTENT: bool = False
    ALLOW_SENDING_WITHOUT_REPLY: bool = True
    LINK_PREVIEW_IS_DISABLED: bool = False
    LINK_PREVIEW_PREFER_SMALL_MEDIA: bool = False
    LINK_PREVIEW_PREFER_LARGE_MEDIA: bool = True
    LINK_PREVIEW_SHOW_ABOVE_TEXT: bool = True
    SHOW_CAPTION_ABOVE_MEDIA: bool = False

    # Разрешения и логирование
    BOT_EDIT: bool = False
    START_INFO_CONSOLE: bool = True
    START_INFO_TO_FILE: bool = True
    LOG_CONSOLE: bool = True
    LOG_FILE: bool = True
    LOG_DIR: Path = Path('Logs')
    LOG_FILE_INFO: Path = Path('bot_info.log')

    # Вебхук
    WEBHOOK: bool = False
    WEBHOOK_URL: str = "https://bot.primo.dpdns.org/webhook"  # публичный HTTPS url
    WEBAPP_HOST: str = "0.0.0.0"  # адрес, на котором слушает uvicorn внутри контейнера
    WEBAPP_PORT: int = 3131
    LOG_LEVEL: str = "warning"
    ACCES_LOG: bool = False

    # API ключи
    API_KEY: Optional[str] = None
    WEB_API_KEY: Optional[str] = None
    WEATHER_API_KEY: Optional[str] = None

    # Пользовательские данные
    TG_API_UID: int = 0
    TG_API_HASH: Optional[str] = None
    SESSION_STRING: Optional[str] = None

    # Идентификаторы
    OWNERS_ID: list[int] = [6751720805, ]
    ADMIN_ID: list[int] = [6751720805, ]
    MODERATOR_ID: int = 0
    IMPORTANT_ID: int = 0
    IMPORTANT_GROUP_ID: int = 0
    IMPORTANT_CHANNEL_ID: int = 0
    SUPPORT_CHAT_ID: int = 0
    SUPPORT_CHAT_ID_TOPIC: int = 0

    # Настройки бота
    PROJECT_NAME: str = "PRIMO"
    BOT_NAME: str = "Первозданная Жемчужина"
    BOT_DESCRIPTION: Optional[str] = None
    BOT_SHORT_DESCRIPTION: Optional[str] = None

    # Ролевой проект
    RP_NAME: Optional[str] = "𝘗𝘳𝘪𝘮𝘰 𝘞𝘰𝘳𝘭𝘥"
    INFO_URL: Optional[str] = "https://t.me/PrimoWorldRP"
    FLUD_URL: Optional[str] = "https://t.me/PrimoWorldRP"
    RP_URL: Optional[str] = "https://t.me/PrimoWorldRP"
    LIFE_URL: Optional[str] = "https://t.me/PrimoWorldRP"
    RP_OWNER: Optional[str] = None
    ROLES: list[str] = ["Альбедо", "Чжун Ли", "Кэйа"]

    # Права администратора
    ANONYMOUS: bool = False
    MANAGE_CHAT: bool = True
    CHANGE_INFO: bool = True
    PROMOTE_MEMBERS: bool = True
    RESTRICT_MEMBERS: bool = True
    POST_MESSAGE: bool = True
    MANAGE_TOPICS: bool = True
    INVITE_USER: bool = True
    DELETE_MESSAGES: bool = True
    MANAGE_VIDEO_CHATS: bool = True
    EDIT_MESSAGES: bool = True
    PIN_MESSAGE: bool = True
    POST_STORIES: bool = True
    EDIT_STORIES: bool = True
    DELETE_STORIES: bool = True

    # ================= ВАЛИДАТОРЫ =================

    @field_validator('PYTHONUNBUFFERED')
    def validate_unbuffered(cls, v: str) -> str:
        """Проверка корректности значения буферизации"""
        if v not in ('0', '1'):
            raise ValueError("PYTHONUNBUFFERED должен быть '0' или '1'")
        return v

    @field_validator('PARSE_MODE')
    def validate_parse_mode(cls, v: str) -> str:
        """Проверка допустимого режима разметки"""
        allowed_modes: set[str] = {"HTML", "Markdown", "MarkdownV2"}
        if v not in allowed_modes:
            raise ValueError(f"Недопустимый PARSE_MODE. Допустимые значения: {', '.join(allowed_modes)}")
        return v

    @field_validator('PREFIX')
    def validate_prefix(cls, v: str) -> str:
        """Очистка и проверка префиксов команд"""
        cleaned: str = ''.join(sorted(set(v), key=v.index))  # Удаление дубликатов с сохранением порядка
        if len(cleaned) < 1:
            raise ValueError("PREFIX должен содержать хотя бы один символ")
        return cleaned

    @field_validator('LOG_DIR', 'LOG_FILE_INFO', mode='before')
    def validate_paths(cls, v: Any) -> Path:
        """Преобразование путей в объекты Path"""
        return Path(v) if isinstance(v, str) else v

    @field_validator('TG_API_UID', 'MODERATOR_ID')
    def validate_ids(cls, v: int) -> int:
        """Проверка корректности идентификаторов"""
        if v < 0:
            raise ValueError("ID не может быть отрицательным")
        return v

    @field_validator('WEBHOOK_URL')
    def validate_webhook_url(cls, v: str) -> str:
        """Базовая проверка URL вебхука"""
        parsed: ParseResult = urlparse(v)
        if not all([parsed.scheme, parsed.netloc]):
            raise ValueError("Некорректный URL вебхука")
        return v

    @field_validator('BOT_NAME', 'PROJECT_NAME', 'OWNER')
    def validate_non_empty(cls, v: str) -> str:
        """Проверка непустых строк"""
        if not v.strip():
            raise ValueError("Поле не может быть пустым")
        return v

    @model_validator(mode='after')
    def validate_bot_token(cls, setting: "Settings") -> "Settings":
        """Проверка наличия необходимых токенов"""
        if setting.DEBUG and not setting.BOT_DEBUG_TOKEN:
            raise ValueError("Требуется BOT_DEBUG_TOKEN в режиме DEBUG")
        if not setting.DEBUG and not setting.BOT_TOKEN:
            raise ValueError("Требуется BOT_TOKEN для рабочего режима")
        return setting

    @model_validator(mode='after')
    def validate_webhook_config(cls, setting: "Settings") -> "Settings":
        """Проверка конфигурации вебхука"""
        if setting.WEBHOOK and not setting.WEBHOOK_URL:
            raise ValueError("WEBHOOK_URL обязателен при включенном WEBHOOK")
        return setting

    @model_validator(mode='after')
    def validate_logging_paths(cls, setting: "Settings") -> "Settings":
        """Создание директорий для логов при необходимости"""
        if setting.LOG_FILE and not setting.LOG_DIR.exists():
            setting.LOG_DIR.mkdir(parents=True, exist_ok=True)
        return setting

    @model_validator(mode='after')
    def set_dynamic_descriptions(cls, setting: "Settings") -> "Settings":
        """Динамическая установка описаний бота"""
        if setting.BOT_DESCRIPTION is None:
            setting.BOT_DESCRIPTION = f"Ваш помощник в удивительные миры! Prod. by:『{setting.OWNER}』"
        if setting.BOT_SHORT_DESCRIPTION is None:
            setting.BOT_SHORT_DESCRIPTION = f"Тех.поддержка: {setting.OWNER}"
        return setting

    # ================= СВОЙСТВА =================

    @property
    def rights(self) -> ChatAdministratorRights:
        """Права администратора бота"""
        return ChatAdministratorRights(
            is_anonymous=self.ANONYMOUS,
            can_manage_chat=self.MANAGE_CHAT,
            can_delete_messages=self.DELETE_MESSAGES,
            can_manage_video_chats=self.MANAGE_VIDEO_CHATS,
            can_restrict_members=self.RESTRICT_MEMBERS,
            can_promote_members=self.PROMOTE_MEMBERS,
            can_change_info=self.CHANGE_INFO,
            can_invite_users=self.INVITE_USER,
            can_post_stories=self.POST_STORIES,
            can_edit_stories=self.EDIT_STORIES,
            can_delete_stories=self.DELETE_STORIES,
            can_post_messages=self.POST_MESSAGE,
            can_edit_messages=self.EDIT_MESSAGES,
            can_pin_messages=self.PIN_MESSAGE,
            can_manage_topics=self.MANAGE_TOPICS,
        )

    @property
    def active_bot_token(self) -> str:
        """Активный токен бота в зависимости от режима"""
        token = self.BOT_DEBUG_TOKEN if self.DEBUG else self.BOT_TOKEN
        if not token:
            raise ValueError("Активный токен бота отсутствует")
        return token

    @property
    def log_dir_absolute(self) -> Path:
        """Абсолютный путь к директории логов"""
        return self.LOG_DIR.absolute()


# Инициализация настроек
settings: Settings = Settings()


# Классы для обратной совместимости и удобства использования

class BotSettings:
    """Алиасы для настроек бота."""
    DEBUG: Final[bool] = settings.DEBUG
    OWNER: Final[str] = settings.OWNER
    BOT_TOKEN: Final[str] = settings.active_bot_token
    PARSE_MODE: Final[str] = settings.PARSE_MODE
    ENCOD: Final[str] = settings.ENCOD
    TIME_FORMAT: Final[str] = settings.TIME_FORMAT
    PREFIX: Final[str] = settings.PREFIX
    BOT_LANGUAGE: Final[str] = settings.BOT_LANGUAGE
    DISABLE_NOTIFICATION: Final[bool] = settings.DISABLE_NOTIFICATION
    PROTECT_CONTENT: Final[bool] = settings.PROTECT_CONTENT
    ALLOW_SENDING_WITHOUT_REPLY: Final[bool] = settings.ALLOW_SENDING_WITHOUT_REPLY
    LINK_PREVIEW_IS_DISABLED: Final[bool] = settings.LINK_PREVIEW_IS_DISABLED
    LINK_PREVIEW_PREFER_SMALL_MEDIA: Final[bool] = settings.LINK_PREVIEW_PREFER_SMALL_MEDIA
    LINK_PREVIEW_PREFER_LARGE_MEDIA: Final[bool] = settings.LINK_PREVIEW_PREFER_LARGE_MEDIA
    LINK_PREVIEW_SHOW_ABOVE_TEXT: Final[bool] = settings.LINK_PREVIEW_SHOW_ABOVE_TEXT
    SHOW_CAPTION_ABOVE_MEDIA: Final[bool] = settings.SHOW_CAPTION_ABOVE_MEDIA


class Permission:
    """Алиасы для разрешений."""
    BOT_EDIT: Final[bool] = settings.BOT_EDIT
    START_INFO_CONSOLE: Final[bool] = settings.START_INFO_CONSOLE
    START_INFO_TO_FILE: Final[bool] = settings.START_INFO_TO_FILE


class LogConfig:
    """Алиасы для конфигурации логов."""
    CONSOLE: Final[bool] = settings.LOG_CONSOLE
    FILE: Final[bool] = settings.LOG_FILE
    DIR: Final[Path] = settings.LOG_DIR
    FILE_INFO: Final[Path] = settings.LOG_FILE_INFO
    ROTATION: ClassVar[str] = '100 MB'
    RETENTION: ClassVar[str] = '7 days'


class Webhook:
    """Алиасы для вебхука."""
    WEBHOOK: Final[bool] = settings.WEBHOOK
    WEBHOOK_URL: Final[str] = settings.WEBHOOK_URL
    WEBHOOK_HOST: Final[str] = settings.WEBAPP_HOST
    WEBHOOK_PORT: Final[int] = settings.WEBAPP_PORT
    LOG_LEVEL: Final[str] = settings.LOG_LEVEL
    ACCES_LOG: Final[bool] = settings.ACCES_LOG


class APISettings:
    """Алиасы для API."""
    API_KEY: Final[Optional[str]] = settings.API_KEY
    WEB_API_KEY: Final[Optional[str]] = settings.WEB_API_KEY
    WEATHER_API_KEY: Final[Optional[str]] = settings.WEATHER_API_KEY


class UserIn:
    """Алиасы для пользовательских данных."""
    TG_API_UID: Final[int] = settings.TG_API_UID
    TG_API_HASH: Final[Optional[str]] = settings.TG_API_HASH
    SESSION_STRING: Final[str] = settings.SESSION_STRING


class ImportantID:
    """Алиасы для важных ID."""
    OWNERS_ID: Final[list[int]] = settings.OWNERS_ID
    ADMIN_ID: Final[list[int]] = settings.ADMIN_ID
    MODERATOR_ID: Final[int] = settings.MODERATOR_ID
    IMPORTANT_ID: Final[int] = settings.IMPORTANT_ID
    IMPORTANT_GROUP_ID: Final[int] = settings.IMPORTANT_GROUP_ID
    IMPORTANT_CHANNEL_ID: Final[int] = settings.IMPORTANT_CHANNEL_ID
    SUPPORT_CHAT_ID: Final[int] = settings.SUPPORT_CHAT_ID
    SUPPORT_CHAT_ID_TOPIC: Final[int] = settings.SUPPORT_CHAT_ID_TOPIC


class BotEdit:
    """Алиасы для настроек редактирования бота."""
    ALLOW: Final[bool] = settings.BOT_EDIT
    PROJECT_NAME: Final[str] = settings.PROJECT_NAME
    NAME: Final[str] = settings.BOT_NAME
    DESCRIPTION: Final[str] = settings.BOT_DESCRIPTION
    SHORT_DESCRIPTION: Final[str] = settings.BOT_SHORT_DESCRIPTION

    ANONYMOUS: Final[bool] = settings.ANONYMOUS
    MANAGE_CHAT: Final[bool] = settings.MANAGE_CHAT
    CHANGE_INFO: Final[bool] = settings.CHANGE_INFO
    PROMOTE_MEMBERS: Final[bool] = settings.PROMOTE_MEMBERS
    RESTRICT_MEMBERS: Final[bool] = settings.RESTRICT_MEMBERS
    POST_MESSAGE: Final[bool] = settings.POST_MESSAGE
    MANAGE_TOPICS: Final[bool] = settings.MANAGE_TOPICS
    INVITE_USER: Final[bool] = settings.INVITE_USER
    DELETE_MESSAGES: Final[bool] = settings.DELETE_MESSAGES
    MANAGE_VIDEO_CHATS: Final[bool] = settings.MANAGE_VIDEO_CHATS
    EDIT_MESSAGES: Final[bool] = settings.EDIT_MESSAGES
    PIN_MESSAGE: Final[bool] = settings.PIN_MESSAGE
    POST_STORIES: Final[bool] = settings.POST_STORIES
    EDIT_STORIES: Final[bool] = settings.EDIT_STORIES
    DELETE_STORIES: Final[bool] = settings.DELETE_STORIES
    RIGHTS: Final[ChatAdministratorRights] = settings.rights


class RpValue:
    """Переменные связанные с ролевым проектом."""
    RP_NAME: Final[str] = settings.RP_NAME
    INFO_URL: str = settings.INFO_URL
    FLUD_URL: str = settings.FLUD_URL
    RP_URL: str = settings.RP_URL
    LIFE_URL: str = settings.LIFE_URL
    RP_OWNER: str = settings.RP_OWNER
    ROLES: list[str] = settings.ROLES


class Project:
    POSTS_DIR: ClassVar[Path] = Path('posts')


class Lists:
    """Интересные списки фактов, цитат и анекдотов."""
    facts: list[str] = [
        "Python был создан Гвидо ван Россумом в 1991 году.",
        "Имена Python и Monty Python связаны — язык назван в честь шоу.",
        "Python — язык с динамической типизацией.",
        "В Python всё является объектом, даже функции и типы данных.",
        "Списки в Python — это изменяемые коллекции, в отличие от кортежей.",
        "Python поддерживает парадигмы ООП, функционального и императивного программирования.",
        "Zen of Python можно увидеть, набрав `import this` в интерпретаторе.",
    ]
    jokes: list[str] = [
        "1",
        "2",
        "3",
        "4",
    ]
    quotes: list[str] = [
        "5",
        "6",
        "7",
        "8",
    ]


# Экспорт совместимых компонентов
__all__ = (
    "BotSettings",
    "LogConfig",
    "Webhook",
    "APISettings",
    "UserIn",
    "ImportantID",
    "Permission",
    "BotEdit",
    "Project",
    "RpValue",
    'settings',
    'Lists',
)
