import os
from enum import Enum
from pathlib import Path
from typing import Any, Optional
from pydantic import (
    field_validator,
    Field,
    BaseModel,
    FilePath,
    ConfigDict,
    DirectoryPath,
)
import logging
logger = logging.getLogger(__name__)


def make_abs(filepath, *args, **kwargs):
    # return os.path.abspath(filepath)
    # return os.path.abspath(filepath)
    from oaa.settings import Config

    if not os.path.isabs(filepath):
        filepath = Path(Config.BASE_DIR) / filepath

    return filepath


def make_abs_orig(filepath, base_dir):
    if not os.path.isabs(filepath):
        filepath = Path(base_dir) / filepath

    return filepath


# TODO Rename these constants to use UPPER_CASE styling
class SourceType(str, Enum):
    none = 'NONE'
    db = 'DB'
    csv = 'CSV'
    csv_push = 'CSV_PUSH'
    api = 'API'
    veza_api = 'VEZA_API'
    source = 'SOURCE'  # A source can source another source, to reuse it
    custom = 'CUSTOM'


class QueryStream(BaseModel):
    query: str
    mapping_filepath: FilePath
    label: str

    @field_validator('mapping_filepath', mode='before')
    @classmethod
    def validate_mapping_filepath(cls, value,
                                  info: dict[str, Any]):

        if value:
            logger.debug('base_dir', info.context['BASE_DIR'])
            value = make_abs(value, info.context['BASE_DIR'])

        return value


class VersionEnum(str, Enum):
    v1 = 'v1'
    v2 = 'v2'


class RunnerType(str, Enum):
    hris = 'HRIS'
    idp = 'IDP'
    custom_app = 'CUSTOM_APP'


class LogLevel(str, Enum):
    debug = 'DEBUG'
    info = 'INFO'
    trace = 'TRACE'
    error = 'ERROR'


DEFAULT_BASE_DIR = os.getcwd()


# This is the base, simple configuration object
class ConfigBase(BaseModel):
    model_config = ConfigDict(validate_default=True)
    config_file: Optional[FilePath] = None
    # base_dir is either set to the containing directory of the
    # config file or defaults to the cwd
    # base_dir: Optional[DirectoryPath] = None
    log_level: Optional[LogLevel] = Field(default=LogLevel.info)

    @field_validator("config_file", mode="before")
    @classmethod
    def config_file_validator(cls, config_file: str,
                              values: dict[str, Any]) -> str:

        if config_file:
            extension = os.path.splitext(config_file)[-1]

            if extension != '.yaml':
                raise ValueError(f'invalid config file extension: {extension}')

        return config_file

    # @field_validator("base_dir", mode="after")
    # @classmethod
    # def basedir_validator(cls, base_dir: str,
    #                       values: dict[str, Any]) -> str:

    #     if not base_dir:
    #         if values.data.get('config_file'):
    #             base_dir = Path(DEFAULT_BASE_DIR) / os.path.dirname(values.data['config_file'])
    #             logger.error('base_dir %s', base_dir)
    #         else:
    #             base_dir = DEFAULT_BASE_DIR

    #         if not base_dir:
    #             raise Exception('base_dir is not set')

    #     return base_dir
