# app/config.py
import os
from pydantic_settings import BaseSettings
from dotenv import load_dotenv
import logging
import secrets
from typing import List

load_dotenv()
logger = logging.getLogger(__name__)

class Settings(BaseSettings):
    DATABASE_URL: str | None = None
    GEMINI_API_KEY: str | None = None
    SENTRY_DSN: str | None = None  # Sentry DSN for error tracking

    # --- Environment Settings ---
    ENVIRONMENT: str = "development"  # development, staging, production

    # --- JWT Settings --- (SECRET_KEY is used by FastAPI-Users)
    SECRET_KEY: str  # Must be set via environment variable
    TOKEN_TYPE: str = "bearer"  # Default token type for JWT authentication
    # FastAPI-Users handles JWT algorithm internally

    # --- OCR Settings ---
    MAX_FILE_SIZE_MB: int = 10  # Maximum allowed file size for OCR processing
    ALLOWED_IMAGE_TYPES: list[str] = ["image/jpeg", "image/png", "image/webp"]  # Supported image formats
    OCR_ITEM_EXTRACTION_PROMPT: str = """
Extract the shopping list items from this image.
List each distinct item on a new line.
Ignore prices, quantities, store names, discounts, taxes, totals, and other non-item text.
Focus only on the names of the products or items to be purchased.
Add 2 underscores before and after the item name, if it is struck through.
If the image does not appear to be a shopping list or receipt, state that clearly.
Example output for a grocery list:
Milk
Eggs
Bread
__Apples__
Organic Bananas
"""
    # --- OCR Error Messages ---
    OCR_SERVICE_UNAVAILABLE: str = "OCR service is currently unavailable. Please try again later."
    OCR_SERVICE_CONFIG_ERROR: str = "OCR service configuration error. Please contact support."
    OCR_UNEXPECTED_ERROR: str = "An unexpected error occurred during OCR processing."
    OCR_QUOTA_EXCEEDED: str = "OCR service quota exceeded. Please try again later."
    OCR_INVALID_FILE_TYPE: str = "Invalid file type. Supported types: {types}"
    OCR_FILE_TOO_LARGE: str = "File too large. Maximum size: {size}MB"
    OCR_PROCESSING_ERROR: str = "Error processing image: {detail}"

    # --- Gemini AI Settings ---
    GEMINI_MODEL_NAME: str = "gemini-2.0-flash"  # The model to use for OCR
    GEMINI_SAFETY_SETTINGS: dict = {
        "HARM_CATEGORY_HATE_SPEECH": "BLOCK_MEDIUM_AND_ABOVE",
        "HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_MEDIUM_AND_ABOVE",
        "HARM_CATEGORY_HARASSMENT": "BLOCK_MEDIUM_AND_ABOVE",
        "HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_MEDIUM_AND_ABOVE",
    }
    GEMINI_GENERATION_CONFIG: dict = {
        "candidate_count": 1,
        "max_output_tokens": 2048,
        "temperature": 0.9,
        "top_p": 1,
        "top_k": 1
    }

    # --- API Settings ---
    API_PREFIX: str = "/api"  # Base path for all API endpoints
    API_OPENAPI_URL: str = "/api/openapi.json"
    API_DOCS_URL: str = "/api/docs"
    API_REDOC_URL: str = "/api/redoc"
    
    # CORS Origins - environment dependent
    CORS_ORIGINS: str = "http://localhost:5173,http://localhost:5174,http://localhost:8000,http://127.0.0.1:5173,http://127.0.0.1:5174,http://127.0.0.1:8000"
    FRONTEND_URL: str = "http://localhost:5173"  # URL for the frontend application

    # --- API Metadata ---
    API_TITLE: str = "Shared Lists API"
    API_DESCRIPTION: str = "API for managing shared shopping lists, OCR, and cost splitting."
    API_VERSION: str = "0.1.0"
    ROOT_MESSAGE: str = "Welcome to the Shared Lists API! Docs available at /api/docs"

    # --- Logging Settings ---
    LOG_LEVEL: str = "WARNING"
    LOG_FORMAT: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

    # --- Health Check Settings ---
    HEALTH_STATUS_OK: str = "ok"
    HEALTH_STATUS_ERROR: str = "error"

    # --- HTTP Status Messages ---
    HTTP_400_DETAIL: str = "Bad Request"
    HTTP_401_DETAIL: str = "Unauthorized"
    HTTP_403_DETAIL: str = "Forbidden"
    HTTP_404_DETAIL: str = "Not Found"
    HTTP_422_DETAIL: str = "Unprocessable Entity"
    HTTP_429_DETAIL: str = "Too Many Requests"
    HTTP_500_DETAIL: str = "Internal Server Error"
    HTTP_503_DETAIL: str = "Service Unavailable"

    # --- Database Error Messages ---
    DB_CONNECTION_ERROR: str = "Database connection error"
    DB_INTEGRITY_ERROR: str = "Database integrity error"
    DB_TRANSACTION_ERROR: str = "Database transaction error"
    DB_QUERY_ERROR: str = "Database query error"

    # --- Auth Error Messages ---
    AUTH_INVALID_CREDENTIALS: str = "Invalid username or password"
    AUTH_NOT_AUTHENTICATED: str = "Not authenticated"
    AUTH_JWT_ERROR: str = "JWT token error: {error}"
    AUTH_JWT_UNEXPECTED_ERROR: str = "Unexpected JWT error: {error}"
    AUTH_HEADER_NAME: str = "WWW-Authenticate"
    AUTH_HEADER_PREFIX: str = "Bearer"

    # OAuth Settings
    # IMPORTANT: For Google OAuth to work, you MUST set the following environment variables
    # (e.g., in your .env file):
    # GOOGLE_CLIENT_ID: Your Google Cloud project's OAuth 2.0 Client ID
    # GOOGLE_CLIENT_SECRET: Your Google Cloud project's OAuth 2.0 Client Secret
    # Ensure the GOOGLE_REDIRECT_URI below matches the one configured in your Google Cloud Console.
    GOOGLE_CLIENT_ID: str = ""
    GOOGLE_CLIENT_SECRET: str = ""
    GOOGLE_REDIRECT_URI: str = "https://mitlistbe.mohamad.dev/api/v1/auth/google/callback"
    
    APPLE_CLIENT_ID: str = ""
    APPLE_TEAM_ID: str = ""
    APPLE_KEY_ID: str = ""
    APPLE_PRIVATE_KEY: str = ""
    APPLE_REDIRECT_URI: str = "https://mitlistbe.mohamad.dev/api/v1/auth/apple/callback"

    # Session Settings
    SESSION_SECRET_KEY: str = "your-session-secret-key"  # Change this in production
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 480  # 8 hours instead of 30 minutes

    # Redis Settings
    REDIS_URL: str = "redis://localhost:6379"
    REDIS_PASSWORD: str = ""

    class Config:
        env_file = ".env"
        env_file_encoding = 'utf-8'
        extra = "ignore"

    @property
    def cors_origins_list(self) -> List[str]:
        """Convert CORS_ORIGINS string to list"""
        return [origin.strip() for origin in self.CORS_ORIGINS.split(",")]

    @property
    def is_production(self) -> bool:
        """Check if running in production environment"""
        return self.ENVIRONMENT.lower() == "production"

    @property
    def is_development(self) -> bool:
        """Check if running in development environment"""
        return self.ENVIRONMENT.lower() == "development"

    @property
    def docs_url(self) -> str | None:
        """Return docs URL only in development"""
        return self.API_DOCS_URL if self.is_development else None

    @property
    def redoc_url(self) -> str | None:
        """Return redoc URL only in development"""
        return self.API_REDOC_URL if self.is_development else None

    @property
    def openapi_url(self) -> str | None:
        """Return OpenAPI URL only in development"""
        return self.API_OPENAPI_URL if self.is_development else None

settings = Settings()

# Validation for critical settings
if settings.DATABASE_URL is None:
    raise ValueError("DATABASE_URL environment variable must be set.")

# Enforce secure secret key
if not settings.SECRET_KEY:
    raise ValueError("SECRET_KEY environment variable must be set. Generate a secure key using: openssl rand -hex 32")

# Validate secret key strength
if len(settings.SECRET_KEY) < 32:
    raise ValueError("SECRET_KEY must be at least 32 characters long for security")

# Production-specific validations
if settings.is_production:
    if settings.SESSION_SECRET_KEY == "your-session-secret-key":
        raise ValueError("SESSION_SECRET_KEY must be changed from default value in production")
    
    if not settings.SENTRY_DSN:
        logger.warning("SENTRY_DSN not set in production environment. Error tracking will be unavailable.")

if settings.GEMINI_API_KEY is None:
    logger.error("CRITICAL: GEMINI_API_KEY environment variable not set. Gemini features will be unavailable.")
else:
    # Optional: Log partial key for confirmation (avoid logging full key)
    logger.info(f"GEMINI_API_KEY loaded (starts with: {settings.GEMINI_API_KEY[:4]}...).")

# Log environment information
logger.info(f"Application starting in {settings.ENVIRONMENT} environment")
if settings.is_production:
    logger.info("Production mode: API documentation disabled")
else:
    logger.info(f"Development mode: API documentation available at {settings.API_DOCS_URL}")