
from decouple import config, Csv


class _Config:
    SECRET_KEY: str = config(
        'SECRET_KEY',
        default='',
    )
    DEBUG: bool = config('DEBUG', default=True, cast=bool)
    ALLOWED_HOSTS: list = config(
        'ALLOWED_HOSTS',
        default='localhost,127.0.0.1,*',
        cast=Csv()
    )

    BACKEND_HOST:  str = config('BACKEND_HOST',  default='127.0.0.1')
    BACKEND_PORT:  int = config('BACKEND_PORT',  default=8000, cast=int)
    FRONTEND_PORT: int = config('FRONTEND_PORT', default=3000, cast=int)

    @property
    def BACKEND_BASE_URL(self) -> str:
        return f'http://{self.BACKEND_HOST}:{self.BACKEND_PORT}'

    @property
    def FRONTEND_BASE_URL(self) -> str:
        return f'http://localhost:{self.FRONTEND_PORT}'
    API_PREFIX = '/api'

    ENDPOINTS = {
        # Market data
        'forex':         '/api/forex/',
        'signals':       '/api/signals/',
        'bots':          '/api/bots/',

        # News
        'news_internal': '/api/news/',
        'news_live':     '/api/news/live/',

        # Education
        'lessons':       '/api/lessons/',

        # Community
        'leaderboard':   '/api/leaderboard/',
        'testimonials':  '/api/testimonials/',

        # Schema / docs  (dev only)
        'schema':        '/api/schema/',
        'swagger':       '/api/docs/',
        'redoc':         '/api/redoc/',
    }

    # =========================================================================
    # WEBSOCKET
    # =========================================================================
    WS_MARKET_PATH:       str = config('WS_MARKET_PATH',      default='/ws/market/')
    WS_GROUP_NAME:        str = config('WS_GROUP_NAME',        default='market_stream')
    WS_HEARTBEAT_INTERVAL: int = config('WS_HEARTBEAT_INTERVAL', default=15,  cast=int)

    # Frontend reconnection strategy (mirrors marketSocket.js values)
    WS_RECONNECT_BASE_MS:     int = config('WS_RECONNECT_BASE_MS',     default=2000, cast=int)
    WS_RECONNECT_MAX_MS:      int = config('WS_RECONNECT_MAX_MS',      default=30000, cast=int)
    WS_RECONNECT_JITTER:      float = config('WS_RECONNECT_JITTER',    default=0.15, cast=float)
    WS_MAX_OFFLINE_ATTEMPTS:  int = config('WS_MAX_OFFLINE_ATTEMPTS',  default=8,    cast=int)
    WS_PING_INTERVAL_MS:      int = config('WS_PING_INTERVAL_MS',      default=25000, cast=int)

    # =========================================================================
    # MARKET DATA PROVIDER
    # =========================================================================
    # Options: 'simulator' | 'polygon' | 'twelvedata' | 'oanda' | 'fxcm'
    MARKET_DATA_PROVIDER: str = config('MARKET_DATA_PROVIDER', default='simulator')

    # Generic key — set whichever provider you activate
    MARKET_DATA_API_KEY:  str = config('MARKET_DATA_API_KEY',  default='')

    # REST fallback polling interval (seconds) when WS is offline
    REST_FALLBACK_INTERVAL_SECONDS: int = config(
        'REST_FALLBACK_INTERVAL_SECONDS', default=5, cast=int
    )

    # =========================================================================
    # EXTERNAL API — MARKETAUX  (live news)
    # =========================================================================
    # Docs:      https://www.marketaux.com/documentation
    # Free tier: 100 requests/day
    # Paid tier: higher limits — same base URL, same endpoint
    MARKETAUX_API_KEY:   str = config('MARKETAUX_API_KEY',   default='')
    MARKETAUX_BASE_URL:  str = config(
        'MARKETAUX_BASE_URL',
        default='https://api.marketaux.com/v1'
    )
    MARKETAUX_NEWS_PATH: str = '/news/all'     # appended to MARKETAUX_BASE_URL

    @property
    def MARKETAUX_NEWS_URL(self) -> str:
        return self.MARKETAUX_BASE_URL + self.MARKETAUX_NEWS_PATH

    MARKETAUX_DEFAULT_LANGUAGE: str = 'en'
    MARKETAUX_DEFAULT_LIMIT:    int = 12
    MARKETAUX_MAX_LIMIT:        int = 50
    MARKETAUX_SORT_BY:          str = 'published_on'

    # Keyword search queries per category
    MARKETAUX_CATEGORY_QUERIES: dict = {
        'forex':       'forex OR "currency market" OR "exchange rate"',
        'crypto':      'cryptocurrency OR bitcoin OR ethereum OR crypto',
        'commodities': 'gold OR oil OR commodities OR "crude oil"',
        'general':     'forex OR crypto OR "stock market" OR trading',
        'default':     'forex OR crypto OR trading OR "financial markets"',
    }

    # =========================================================================
    # EXTERNAL API — POLYGON.IO  (optional market data upgrade)
    # =========================================================================
    # Docs: https://polygon.io/docs
    POLYGON_API_KEY:  str = config('POLYGON_API_KEY',  default='')
    POLYGON_BASE_URL: str = config(
        'POLYGON_BASE_URL',
        default='https://api.polygon.io/v2'
    )

    # =========================================================================
    # EXTERNAL API — TWELVE DATA  (optional market data upgrade)
    # =========================================================================
    # Docs: https://twelvedata.com/docs
    TWELVEDATA_API_KEY:  str = config('TWELVEDATA_API_KEY',  default='')
    TWELVEDATA_BASE_URL: str = config(
        'TWELVEDATA_BASE_URL',
        default='https://api.twelvedata.com'
    )

    # =========================================================================
    # EXTERNAL API — OANDA  (optional forex provider)
    # =========================================================================
    # Docs: https://developer.oanda.com/rest-live-v20/introduction/
    OANDA_API_KEY:       str = config('OANDA_API_KEY',   default='')
    OANDA_ACCOUNT_ID:    str = config('OANDA_ACCOUNT_ID', default='')
    OANDA_ENVIRONMENT:   str = config('OANDA_ENVIRONMENT', default='practice')   # 'practice' | 'live'
    OANDA_BASE_URL:      str = config(
        'OANDA_BASE_URL',
        default='https://api-fxtrade.oanda.com/v3'          # live
    )
    OANDA_PRACTICE_URL:  str = 'https://api-fxpractice.oanda.com/v3'

    @property
    def OANDA_ACTIVE_URL(self) -> str:
        return (
            self.OANDA_PRACTICE_URL
            if self.OANDA_ENVIRONMENT == 'practice'
            else self.OANDA_BASE_URL
        )

    # =========================================================================
    # EXTERNAL API — ALPHA VANTAGE  (optional free market data)
    # =========================================================================
    # Docs: https://www.alphavantage.co/documentation/
    ALPHAVANTAGE_API_KEY:  str = config('ALPHAVANTAGE_API_KEY',  default='')
    ALPHAVANTAGE_BASE_URL: str = 'https://www.alphavantage.co/query'

    # =========================================================================
    # PAYMENT — STRIPE  (future subscriptions)
    # =========================================================================
    # Docs: https://stripe.com/docs/api
    STRIPE_SECRET_KEY:      str = config('STRIPE_SECRET_KEY',      default='')
    STRIPE_PUBLISHABLE_KEY: str = config('STRIPE_PUBLISHABLE_KEY', default='')
    STRIPE_WEBHOOK_SECRET:  str = config('STRIPE_WEBHOOK_SECRET',  default='')
    STRIPE_BASE_URL:        str = 'https://api.stripe.com/v1'
    STRIPE_PRICE_IDS: dict = {
        'pro_monthly':  config('STRIPE_PRICE_PRO_MONTHLY',  default=''),
        'pro_annual':   config('STRIPE_PRICE_PRO_ANNUAL',   default=''),
        'vip_monthly':  config('STRIPE_PRICE_VIP_MONTHLY',  default=''),
        'vip_annual':   config('STRIPE_PRICE_VIP_ANNUAL',   default=''),
    }

    # =========================================================================
    # EMAIL — SENDGRID  (future notifications)
    # =========================================================================
    # Docs: https://docs.sendgrid.com/api-reference
    SENDGRID_API_KEY:  str = config('SENDGRID_API_KEY', default='')
    SENDGRID_BASE_URL: str = 'https://api.sendgrid.com/v3'
    EMAIL_FROM:        str = config('EMAIL_FROM', default='noreply@thestarfx.com')
    EMAIL_FROM_NAME:   str = config('EMAIL_FROM_NAME', default='TheStarFX')

    # =========================================================================
    # CACHE / REDIS  (production channel layer & caching)
    # =========================================================================
    REDIS_URL: str = config('REDIS_URL', default='redis://127.0.0.1:6379/1')

    # =========================================================================
    # DATABASE
    # =========================================================================
    DATABASE_URL: str = config('DATABASE_URL', default='')   # empty → SQLite default

    # =========================================================================
    # CORS ORIGINS
    # =========================================================================
    CORS_ALLOWED_ORIGINS: list = config(
        'CORS_ALLOWED_ORIGINS',
        default=(
            'http://localhost:8000,'
            'http://localhost:3000,'
            'http://localhost:8080,'
            'http://127.0.0.1:8000,'
            'http://127.0.0.1:3000'
        ),
        cast=Csv()
    )

    # =========================================================================
    # HTTP CLIENT DEFAULTS
    # =========================================================================
    HTTP_TIMEOUT_SECONDS:   float = config('HTTP_TIMEOUT_SECONDS',   default=8.0,  cast=float)
    HTTP_CONNECT_TIMEOUT:   float = config('HTTP_CONNECT_TIMEOUT',   default=5.0,  cast=float)
    HTTP_MAX_RETRIES:       int   = config('HTTP_MAX_RETRIES',       default=2,    cast=int)


# Singleton instance — import this everywhere
cfg = _Config()
