"""
Chart API Endpoints

This module provides API endpoints for chart data (historical price data).
"""

from datetime import datetime
from typing import List, Optional

from fastapi import APIRouter, HTTPException, Query
from loguru import logger
from pydantic import BaseModel

from optrabot.broker.brokerconnector import ChartInterval
from optrabot.broker.brokerfactory import BrokerFactory

router = APIRouter(prefix='/api')


class OHLCBarResponse(BaseModel):
    """Single OHLC bar for chart data"""
    time: int  # Unix timestamp in seconds
    open: float
    high: float
    low: float
    close: float
    volume: int = 0


class ChartDataResponse(BaseModel):
    """Response model for chart data"""
    symbol: str
    interval: str
    bars: List[OHLCBarResponse]


class StrikeLegInfo(BaseModel):
    """Strike leg information for chart overlay"""
    strike: float
    right: str  # 'CALL' or 'PUT'
    action: str  # 'BUY' or 'SELL'


class ChartRequest(BaseModel):
    """Request model for chart data with trade context"""
    symbol: str
    interval: str = '15m'
    start_time: Optional[str] = None  # ISO format datetime
    end_time: Optional[str] = None    # ISO format datetime
    bars: int = 100


@router.get('/chart/{symbol}', response_model=ChartDataResponse)
async def get_chart_data(
    symbol: str,
    interval: str = Query(default='15m', description='Bar interval: 1m, 5m, 15m, 1h, 1d'),
    start: Optional[str] = Query(default=None, description='Start datetime in ISO format'),
    end: Optional[str] = Query(default=None, description='End datetime in ISO format'),
    bars: int = Query(default=100, description='Number of bars if start not specified')
) -> ChartDataResponse:
    """
    Get historical price data for a symbol.
    
    This endpoint returns OHLC bars for chart visualization.
    The data is fetched from the connected broker.
    
    Args:
        symbol: Trading symbol (e.g., SPX, SPY, QQQ)
        interval: Bar interval (1m, 5m, 15m, 1h, 1d)
        start: Start datetime in ISO format (optional)
        end: End datetime in ISO format (optional, defaults to now)
        bars: Number of bars to return if start not specified
        
    Returns:
        ChartDataResponse with OHLC bars
    """
    try:
        # Get an active broker connector
        broker_factory = BrokerFactory()
        connectors = broker_factory.get_broker_connectors()
        
        # Find the first connected connector
        connector = None
        for conn in connectors.values():
            if conn.isConnected():
                connector = conn
                break
        
        if connector is None:
            raise HTTPException(
                status_code=503,
                detail='No active broker connection available'
            )
        
        # Parse datetime parameters
        start_dt = None
        end_dt = None
        
        if start:
            try:
                start_dt = datetime.fromisoformat(start.replace('Z', '+00:00'))
            except ValueError as e:
                raise HTTPException(
                    status_code=400,
                    detail=f'Invalid start datetime format: {start}'
                ) from e
        
        if end:
            try:
                end_dt = datetime.fromisoformat(end.replace('Z', '+00:00'))
            except ValueError as e:
                raise HTTPException(
                    status_code=400,
                    detail=f'Invalid end datetime format: {end}'
                ) from e
        
        # Validate and convert interval to enum
        try:
            chart_interval = ChartInterval.from_string(interval)
        except ValueError as e:
            raise HTTPException(
                status_code=400,
                detail=str(e)
            ) from e
        
        # Fetch price history from broker
        logger.debug(f'Fetching chart data for {symbol}, interval={chart_interval.value}, start={start_dt}, end={end_dt}, bars={bars}')
        
        ohlc_bars = await connector.get_price_history(
            symbol=symbol,
            interval=chart_interval,
            start=start_dt,
            end=end_dt,
            bars=bars
        )
        
        if not ohlc_bars:
            logger.warning(f'No chart data available for {symbol}')
            return ChartDataResponse(
                symbol=symbol,
                interval=interval,
                bars=[]
            )
        
        # Convert to response format
        response_bars = [
            OHLCBarResponse(
                time=bar.to_dict()['time'],
                open=bar.open,
                high=bar.high,
                low=bar.low,
                close=bar.close,
                volume=bar.volume
            )
            for bar in ohlc_bars
        ]
        
        logger.debug(f'Returning {len(response_bars)} bars for {symbol}')
        
        return ChartDataResponse(
            symbol=symbol,
            interval=interval,
            bars=response_bars
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f'Error fetching chart data for {symbol}: {e}')
        raise HTTPException(
            status_code=500,
            detail=f'Error fetching chart data: {str(e)}'
        ) from e
