# -*- coding:utf-8 -*-

import re
from functools import lru_cache
from typing import Optional

from pydantic import field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class AppSettings(BaseSettings):
    odoo_host: str = 'http://odoo:8069'
    odoo_db: str
    jwt_secret_key: str
    aes_secret_key: str
    hash_algorithm: str = 'HS256'
    rate_limit: str = '100/minute'
    access_token_expire_minutes: int = 60
    limit_search_records: Optional[int] = 50
    limit_create_records: Optional[int] = 50
    cors_origins: str = '*'
    limiter_storage_uri: str | None = None

    model_config = SettingsConfigDict(
        extra='ignore',
        env_file=('conf/.env',),
        env_file_encoding='utf-8',
    )

    @field_validator('jwt_secret_key', 'aes_secret_key')
    @classmethod
    def validate_secret_keys(cls, v: str, info) -> str:
        if len(v) < 32:
            raise ValueError(f'{info.field_name} must be at least 32 characters')
        return v

    @field_validator('rate_limit')
    @classmethod
    def validate_rate_limit(cls, v: str) -> str:
        if not re.match(r'^\d+/(second|minute|hour|day)$', v):
            raise ValueError('rate_limit must match format like "100/minute"')
        return v

    @field_validator('access_token_expire_minutes')
    @classmethod
    def validate_expire_minutes(cls, v: int) -> int:
        if v <= 0:
            raise ValueError('access_token_expire_minutes must be positive')
        return v

    @field_validator('limit_search_records', 'limit_create_records')
    @classmethod
    def validate_limits(cls, v: Optional[int], info) -> Optional[int]:
        if v is not None and v <= 0:
            raise ValueError(f'{info.field_name} must be positive')
        return v

    @field_validator('odoo_host')
    @classmethod
    def validate_odoo_host(cls, v: str) -> str:
        if not re.match(r'^https?://', v):
            raise ValueError('odoo_host must be a valid HTTP(S) URL')
        return v


@lru_cache()
def get_settings():
    return AppSettings()
