"""FastAPI REST API for ADS1115 ADC device."""

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from typing import Optional, List

from ..service import get_service, ADS1115Config, reset_service


def create_api_app() -> FastAPI:
    """Create and configure FastAPI application."""
    app = FastAPI(
        title="piADC - ADS1115 ADC API",
        description="REST API for accessing ADS1115 16-bit ADC on Raspberry Pi",
        version="1.0.0"
    )

    class ChannelRead(BaseModel):
        channel: int = Field(..., ge=0, le=3, description="ADC channel (0-3)")
        raw_value: int
        voltage: float
        gain: float
        data_rate: int

    class AllChannelsRead(BaseModel):
        channels: List[ChannelRead]
        mock_mode: bool
        i2c_address: str

    class DeviceConfig(BaseModel):
        i2c_address: str = "0x48"
        gain: float = 1.0
        data_rate: int = 128
        mode: str = "single"
        mock_mode: bool = False
        available_gains: List[float] = []
        available_data_rates: List[int] = []

    class ConfigUpdate(BaseModel):
        gain: Optional[float] = Field(None, ge=2/3, le=16)
        data_rate: Optional[int] = Field(None, ge=8, le=860)
        i2c_address: Optional[str] = None
        mode: Optional[str] = Field(None, pattern="^(single|continuous)$")

    class ChannelRequest(BaseModel):
        channel: int = Field(..., ge=0, le=3, description="ADC channel to read (0-3)")

    @app.get("/")
    async def root():
        """API information."""
        return {
            "name": "piADC - ADS1115 ADC API",
            "version": "1.0.0",
            "endpoints": [
                "/health",
                "/config",
                "/read/{channel}",
                "/read/all"
            ]
        }

    @app.get("/health")
    async def health():
        """Check ADC service health."""
        service = get_service()
        return {
            "status": "healthy",
            "initialized": service._adc is not None,
            "mock_mode": service.is_mock
        }

    @app.get("/config", response_model=DeviceConfig)
    async def get_config():
        """Get current device configuration."""
        service = get_service()
        config = service.get_config()
        return DeviceConfig(**config)

    @app.post("/config", response_model=DeviceConfig)
    async def update_config(update: ConfigUpdate):
        """Update device configuration."""
        service = get_service()
        kwargs = {k: v for k, v in update.model_dump().items() if v is not None}
        config = service.update_config(**kwargs)
        return DeviceConfig(**config)

    @app.get("/read/all", response_model=AllChannelsRead)
    async def read_all():
        """Read all 4 ADC channels."""
        service = get_service()
        result = service.read_all_channels()
        return AllChannelsRead(**result)

    @app.get("/read/{channel}", response_model=ChannelRead)
    async def read_channel(channel: int):
        """Read a single ADC channel."""
        if channel < 0 or channel > 3:
            raise HTTPException(status_code=400, detail="Channel must be 0-3")
        
        service = get_service()
        result = service.read_channel(channel)
        return ChannelRead(**result)

    @app.post("/read/channel", response_model=ChannelRead)
    async def read_channel_post(request: ChannelRequest):
        """Read a single ADC channel (POST method)."""
        service = get_service()
        result = service.read_channel(request.channel)
        return ChannelRead(**result)

    @app.post("/reset")
    async def reset_service_endpoint():
        """Reset ADC service (useful for reconfiguration)."""
        reset_service()
        return {"status": "reset", "message": "Service reset. Call /health to reinitialize."}

    return app


# Global app instance for uvicorn
app = create_api_app()


def main():
    """Run API server."""
    import uvicorn
    import os
    host = os.getenv("API_HOST", "0.0.0.0")
    port = int(os.getenv("API_PORT", "8000"))
    uvicorn.run(app, host=host, port=port)


if __name__ == "__main__":
    main()
