# app/main.py
import sys
import os
import json
import tomllib
from pathlib import Path
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app import ssl_heidi


from app.routers import (
    address,
    contact,
    proposal,
    dewar,
    shipment,
    puck,
    spreadsheet,
    logistics,
    auth,
    sample,
)
from app.database import Base, engine, SessionLocal, load_sample_data


# Utility function to fetch metadata from pyproject.toml
def get_project_metadata():
    # Dynamically resolve the correct path to pyproject.toml
    current_dir = Path(__file__).resolve().parent
    root_dir = current_dir.parent.parent  # Adjust based on structure
    pyproject_path = root_dir / "pyproject.toml"

    if not pyproject_path.exists():
        raise FileNotFoundError(f"pyproject.toml not found at {pyproject_path}")

    with open(pyproject_path, "rb") as f:
        pyproject = tomllib.load(f)
        name = pyproject["project"]["name"]
        version = pyproject["project"]["version"]
        return name, version


# Get project metadata from pyproject.toml
project_name, project_version = get_project_metadata()
app = FastAPI(
    title=project_name,  # Syncs with project `name`
    description="Backend for next-gen sample management system",
    version=project_version,  # Syncs with project `version`
)

# Determine environment and configuration file path
environment = os.getenv("ENVIRONMENT", "dev")
config_file = Path(__file__).resolve().parent.parent / f"config_{environment}.json"

# Load configuration
with open(config_file) as f:
    config = json.load(f)

cert_path = config["ssl_cert_path"]
key_path = config["ssl_key_path"]

# Generate SSL Key and Certificate if not exist (only for development)
if environment == "dev":
    Path("ssl").mkdir(parents=True, exist_ok=True)
    if not Path(cert_path).exists() or not Path(key_path).exists():
        ssl_heidi.generate_self_signed_cert(cert_path, key_path)

# Apply CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Enable CORS for all origins
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.on_event("startup")
def on_startup():
    # Drop and recreate database schema
    Base.metadata.drop_all(bind=engine)
    Base.metadata.create_all(bind=engine)

    db = SessionLocal()
    try:
        load_sample_data(db)
    finally:
        db.close()


# Include routers with correct configuration
app.include_router(auth.router, prefix="/auth", tags=["auth"])
app.include_router(contact.router, prefix="/contacts", tags=["contacts"])
app.include_router(address.router, prefix="/addresses", tags=["addresses"])
app.include_router(proposal.router, prefix="/proposals", tags=["proposals"])
app.include_router(dewar.router, prefix="/dewars", tags=["dewars"])
app.include_router(shipment.router, prefix="/shipments", tags=["shipments"])
app.include_router(puck.router, prefix="/pucks", tags=["pucks"])
app.include_router(spreadsheet.router, tags=["spreadsheet"])
app.include_router(logistics.router, prefix="/logistics", tags=["logistics"])
app.include_router(sample.router, prefix="/samples", tags=["samples"])


if __name__ == "__main__":
    import uvicorn

    # Check if the user has passed "generate-openapi" as the first CLI argument
    if len(sys.argv) > 1 and sys.argv[1] == "generate-openapi":
        # Generate and save the OpenAPI schema
        openapi_schema = app.openapi()
        with open("openapi.json", "w") as openapi_file:
            json.dump(openapi_schema, openapi_file, indent=2)
        print("OpenAPI schema has been generated and saved to 'openapi.json'.")
    else:
        # Default behavior: Run the FastAPI server
        import os
        from multiprocessing import Process
        from time import sleep

        # Get environment from an environment variable
        environment = os.getenv("ENVIRONMENT", "dev")
        is_ci = os.getenv("CI", "false").lower() == "true"  # Check if running in CI
        port = int(os.getenv("PORT", 8000))  # Default to 8000 if PORT is not set

        # Paths for SSL certificates
        if is_ci:
            cert_path = "ssl/cert.pem"
            key_path = "ssl/key.pem"
            host = "127.0.0.1"
            print("Running in CI mode with self-signed certificates...")
            # Ensure SSL certificate and key are generated
            if is_ci or environment == "dev":
                Path("ssl").mkdir(exist_ok=True)

                if not Path(cert_path).exists() or not Path(key_path).exists():
                    print(
                        f"Generating self-signed SSL certificate"
                        f"at {cert_path} and {key_path}"
                    )
                    ssl_heidi.generate_self_signed_cert(cert_path, key_path)
        elif environment == "test":
            cert_path = "ssl/mx-aare-test.psi.ch.pem"
            key_path = "ssl/mx-aare-test.psi.ch.key"
            host = "0.0.0.0"
            print("Using test SSL certificates...")
        else:
            cert_path = "ssl/cert.pem"
            key_path = "ssl/key.pem"
            host = "127.0.0.1"
            print("Using development SSL certificates...")

        def run_server():
            uvicorn.run(
                app,
                host=host,
                port=port,
                log_level="debug",
                ssl_keyfile=key_path,
                ssl_certfile=cert_path,
            )

        if is_ci:
            # In CI, start server in a subprocess and exit after a short delay
            server_process = Process(target=run_server)
            server_process.start()
            sleep(5)  # Wait for 5 seconds to ensure the server starts without errors
            server_process.terminate()  # Terminate the server process
            server_process.join()  # Clean up the process
            print("CI: Server started successfully and exited.")
        else:
            # Normal behavior for running the FastAPI server
            run_server()
