#!/usr/bin/env python3
import logging
from pathlib import Path
from plumbum import cli
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
import uvicorn

# Logging configuration
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[logging.StreamHandler()]
)
logger = logging.getLogger(__name__)

# FastAPI application
app = FastAPI()
db_dir = None  # This will be set by the CLI application

@app.get("/db/{file_path:path}")
def serve_file(file_path: str):
    """
    Serve files from the database directory, such as .zip files or metadata.json.
    """
    logger.info(f"Requested file: {file_path}")
    # Resolve symlink
    resolved_path = Path(file_path).resolve(strict=True)
    logger.info(f"file resolved to: {resolved_path}")
    if not resolved_path.exists():
        logger.error(f"File not found: {resolved_path}")
        raise HTTPException(status_code=404, detail=f"{resolved_path} not found")
    return FileResponse(resolved_path)


@app.get("/index")
@app.get("/api/v1/latest_results/codeql-all")
def serve_metadata_json():
    """
    Serve the metadata.json file for multiple routes.
    """
    metadata_path = Path(db_dir) / "metadata.json"
    logger.info(f"Requested metadata.json at: {metadata_path}")
    if not metadata_path.exists():
        logger.error("metadata.json not found.")
        raise HTTPException(status_code=404, detail="metadata.json not found")
    logger.info(f"Serving metadata.json from: {metadata_path}")
    return FileResponse(metadata_path)

@app.middleware("http")
async def log_request(request, call_next):
    logger.info(f"Incoming request: {request.method} {request.url}")
    response = await call_next(request)
    return response

class DBService(cli.Application):
    """
    DBService serves:
    1. CodeQL database .zip files symlinked in the --codeql-db-dir
    2. Metadata for those zip files, contained in metadata.json in the same
       directory.
    The HTTP endpoints are:
    1. /db/{filename}
    2. /index
    3. /api/v1/latest_results/codeql-all
    """

    codeql_db_dir = cli.SwitchAttr("--codeql-db-dir", str, mandatory=True,
                                   help="Directory containing CodeQL database files")
    host = cli.SwitchAttr("--host", str, default="127.0.0.1",
                          help="Host address for the HTTP server")
    port = cli.SwitchAttr("--port", int, default=8080, help="Port for the HTTP server")

    def main(self):
        global db_dir
        db_dir = Path(self.codeql_db_dir)
        if not db_dir.is_dir():
            logger.error(f"Invalid directory: {db_dir}")
            return 1

        logger.info(f"Starting server at {self.host}:{self.port}")
        logger.info(f"Serving files from directory: {db_dir}")

        # Run the FastAPI server using Uvicorn
        uvicorn.run(app, host=self.host, port=self.port)


if __name__ == "__main__":
    DBService.run()
