"""
TK-MP-Project 설정 관리
환경별 설정을 중앙화하여 관리
"""
import os
from typing import List, Optional, Dict, Any
from pathlib import Path
from pydantic_settings import BaseSettings
from pydantic import Field, validator
import json


class DatabaseSettings(BaseSettings):
    """데이터베이스 설정"""
    url: str = Field(
        default="postgresql://tkbom_user:tkbom_password@tkeg-postgres:5432/tk_bom",
        description="데이터베이스 연결 URL"
    )
    pool_size: int = Field(default=10, description="연결 풀 크기")
    max_overflow: int = Field(default=20, description="최대 오버플로우")
    pool_timeout: int = Field(default=30, description="연결 타임아웃 (초)")
    pool_recycle: int = Field(default=3600, description="연결 재활용 시간 (초)")
    echo: bool = Field(default=False, description="SQL 로그 출력 여부")
    
    class Config:
        env_prefix = "DB_"


class RedisSettings(BaseSettings):
    """Redis 설정"""
    url: str = Field(default="redis://redis:6379", description="Redis 연결 URL")
    max_connections: int = Field(default=20, description="최대 연결 수")
    socket_timeout: int = Field(default=5, description="소켓 타임아웃 (초)")
    socket_connect_timeout: int = Field(default=5, description="연결 타임아웃 (초)")
    retry_on_timeout: bool = Field(default=True, description="타임아웃 시 재시도")
    decode_responses: bool = Field(default=False, description="응답 디코딩 여부")
    
    class Config:
        env_prefix = "REDIS_"


class SecuritySettings(BaseSettings):
    """보안 설정"""
    cors_origins: List[str] = Field(default=[], description="CORS 허용 도메인")
    cors_methods: List[str] = Field(
        default=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
        description="CORS 허용 메서드"
    )
    cors_headers: List[str] = Field(
        default=["*"],
        description="CORS 허용 헤더"
    )
    cors_credentials: bool = Field(default=True, description="CORS 자격증명 허용")
    
    # 파일 업로드 보안
    max_file_size: int = Field(default=50 * 1024 * 1024, description="최대 파일 크기 (bytes)")
    allowed_file_extensions: List[str] = Field(
        default=['.xlsx', '.xls', '.csv'],
        description="허용된 파일 확장자"
    )
    upload_path: str = Field(default="uploads", description="업로드 경로")
    
    # API 보안
    api_key_header: str = Field(default="X-API-Key", description="API 키 헤더명")
    rate_limit_per_minute: int = Field(default=100, description="분당 요청 제한")
    
    class Config:
        env_prefix = "SECURITY_"


class LoggingSettings(BaseSettings):
    """로깅 설정"""
    level: str = Field(default="INFO", description="로그 레벨")
    file_path: str = Field(default="logs/app.log", description="로그 파일 경로")
    max_file_size: int = Field(default=10 * 1024 * 1024, description="로그 파일 최대 크기")
    backup_count: int = Field(default=5, description="백업 파일 수")
    format: str = Field(
        default="%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s",
        description="로그 포맷"
    )
    date_format: str = Field(default="%Y-%m-%d %H:%M:%S", description="날짜 포맷")
    
    # 환경별 로그 레벨
    development_level: str = Field(default="DEBUG", description="개발 환경 로그 레벨")
    production_level: str = Field(default="INFO", description="운영 환경 로그 레벨")
    test_level: str = Field(default="WARNING", description="테스트 환경 로그 레벨")
    
    class Config:
        env_prefix = "LOG_"


class PerformanceSettings(BaseSettings):
    """성능 설정"""
    # 캐시 설정
    cache_ttl_default: int = Field(default=3600, description="기본 캐시 TTL (초)")
    cache_ttl_files: int = Field(default=300, description="파일 목록 캐시 TTL")
    cache_ttl_materials: int = Field(default=600, description="자재 목록 캐시 TTL")
    cache_ttl_jobs: int = Field(default=1800, description="작업 목록 캐시 TTL")
    cache_ttl_classification: int = Field(default=3600, description="분류 결과 캐시 TTL")
    cache_ttl_statistics: int = Field(default=900, description="통계 데이터 캐시 TTL")
    
    # 파일 처리 설정
    chunk_size: int = Field(default=1000, description="파일 처리 청크 크기")
    max_workers: int = Field(default=4, description="최대 워커 수")
    memory_limit_mb: int = Field(default=512, description="메모리 제한 (MB)")
    
    class Config:
        env_prefix = "PERF_"


class Settings(BaseSettings):
    """메인 애플리케이션 설정"""
    
    # 기본 설정
    app_name: str = Field(default="TK-EG BOM Management API", description="애플리케이션 이름")
    app_version: str = Field(default="1.0.0", description="애플리케이션 버전")
    app_description: str = Field(
        default="자재 분류 및 프로젝트 관리 시스템",
        description="애플리케이션 설명"
    )
    debug: bool = Field(default=False, description="디버그 모드")
    
    # 환경 설정
    environment: str = Field(
        default="development",
        description="실행 환경 (development, production, test, synology)"
    )
    
    # 서버 설정
    host: str = Field(default="0.0.0.0", description="서버 호스트")
    port: int = Field(default=8000, description="서버 포트")
    reload: bool = Field(default=False, description="자동 재로드")
    workers: int = Field(default=1, description="워커 프로세스 수")
    
    # 하위 설정들
    database: DatabaseSettings = Field(default_factory=DatabaseSettings)
    redis: RedisSettings = Field(default_factory=RedisSettings)
    security: SecuritySettings = Field(default_factory=SecuritySettings)
    logging: LoggingSettings = Field(default_factory=LoggingSettings)
    performance: PerformanceSettings = Field(default_factory=PerformanceSettings)
    
    # 추가 설정
    timezone: str = Field(default="Asia/Seoul", description="시간대")
    language: str = Field(default="ko", description="기본 언어")
    
    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"
        case_sensitive = False
        extra = "ignore"
        
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._setup_environment_specific_settings()
        self._setup_cors_origins()
        self._validate_settings()
    
    @validator('environment')
    def validate_environment(cls, v):
        """환경 값 검증"""
        allowed_environments = ['development', 'production', 'test', 'synology']
        if v not in allowed_environments:
            raise ValueError(f'Environment must be one of: {allowed_environments}')
        return v
    
    @validator('port')
    def validate_port(cls, v):
        """포트 번호 검증"""
        if not 1 <= v <= 65535:
            raise ValueError('Port must be between 1 and 65535')
        return v
    
    def _setup_environment_specific_settings(self):
        """환경별 특정 설정 적용"""
        if self.environment == "development":
            self.debug = True
            self.reload = True
            self.database.echo = True
            self.logging.level = self.logging.development_level
            
        elif self.environment == "production":
            self.debug = False
            self.reload = False
            self.database.echo = False
            self.logging.level = self.logging.production_level
            self.workers = max(2, os.cpu_count() or 1)
            
        elif self.environment == "test":
            self.debug = False
            self.reload = False
            self.database.echo = False
            self.logging.level = self.logging.test_level
            # 테스트용 인메모리 데이터베이스
            self.database.url = "sqlite:///:memory:"
            
        elif self.environment == "synology":
            self.debug = False
            self.reload = False
            self.host = "0.0.0.0"
            self.port = 10080
    
    def _setup_cors_origins(self):
        """환경별 CORS origins 설정"""
        if not self.security.cors_origins:
            cors_config = {
                "development": [
                    "http://localhost:3000",
                    "http://localhost:5173",
                    "http://localhost:13000",
                    "http://127.0.0.1:3000",
                    "http://127.0.0.1:5173",
                    "http://127.0.0.1:13000"
                ],
                "production": [
                    "https://tkeg.technicalkorea.net",
                    "https://tkfb.technicalkorea.net",
                    "https://tkreport.technicalkorea.net",
                    "https://tkqc.technicalkorea.net",
                    "https://tkuser.technicalkorea.net",
                ],
                "synology": [
                    "http://192.168.0.3:10173",
                    "http://localhost:10173"
                ],
                "test": [
                    "http://testserver"
                ]
            }
            
            self.security.cors_origins = cors_config.get(
                self.environment, 
                cors_config["development"]
            )
    
    def _validate_settings(self):
        """설정 검증"""
        # 로그 디렉토리 생성
        log_dir = Path(self.logging.file_path).parent
        log_dir.mkdir(parents=True, exist_ok=True)
        
        # 업로드 디렉토리 생성
        upload_dir = Path(self.security.upload_path)
        upload_dir.mkdir(parents=True, exist_ok=True)
    
    def get_database_url(self) -> str:
        """데이터베이스 URL 반환"""
        return self.database.url
    
    def get_redis_url(self) -> str:
        """Redis URL 반환"""
        return self.redis.url
    
    def is_development(self) -> bool:
        """개발 환경 여부"""
        return self.environment == "development"
    
    def is_production(self) -> bool:
        """운영 환경 여부"""
        return self.environment == "production"
    
    def is_test(self) -> bool:
        """테스트 환경 여부"""
        return self.environment == "test"
    
    def get_cors_config(self) -> Dict[str, Any]:
        """CORS 설정 반환"""
        return {
            "allow_origins": self.security.cors_origins,
            "allow_methods": self.security.cors_methods,
            "allow_headers": self.security.cors_headers,
            "allow_credentials": self.security.cors_credentials
        }
    
    def to_dict(self) -> Dict[str, Any]:
        """설정을 딕셔너리로 변환"""
        return self.dict()
    
    def save_to_file(self, file_path: str):
        """설정을 파일로 저장"""
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(self.to_dict(), f, indent=2, ensure_ascii=False, default=str)


# 전역 설정 인스턴스
settings = Settings()


def get_settings() -> Settings:
    """설정 인스턴스 반환"""
    return settings
