# app/main.py
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, load_slots_data


# Utility function to fetch metadata from pyproject.toml
def get_project_metadata():
    # Start from the current script's directory and search for pyproject.toml
    script_dir = Path(__file__).resolve().parent
    for parent in script_dir.parents:
        pyproject_path = parent / "pyproject.toml"
        if pyproject_path.exists():
            with open(pyproject_path, "rb") as f:
                pyproject = tomllib.load(f)
                name = pyproject["project"]["name"]
                version = pyproject["project"]["version"]
                return name, version

    # If no pyproject.toml is found, raise FileNotFoundError
    raise FileNotFoundError(
        f"pyproject.toml not found in any parent directory of {script_dir}"
    )


# 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():
    db = SessionLocal()
    try:
        if environment == "prod":
            from sqlalchemy.engine import reflection

            inspector = reflection.Inspector.from_engine(engine)
            tables_exist = inspector.get_table_names()

            if not tables_exist:
                print("Production database is empty. Initializing...")
                Base.metadata.create_all(bind=engine)
                load_slots_data(db)
            else:
                print("Production database already initialized.")

        else:  # dev or test
            print(f"{environment.capitalize()} environment: Regenerating database.")
            Base.metadata.drop_all(bind=engine)
            Base.metadata.create_all(bind=engine)
            if environment == "dev":
                load_sample_data(db)
            elif environment == "test":
                load_slots_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
    from pathlib import Path
    from app import ssl_heidi
    from dotenv import load_dotenv

    # Load environment variables from .env file
    load_dotenv()

    # Fetch environment values
    environment = os.getenv("ENVIRONMENT", "dev")
    port = int(os.getenv("PORT", 8000))  # Default to 8000 if PORT is not set
    is_ci = (
        os.getenv("CI", "false").lower() == "true"
    )  # Detect if running in CI environment

    # Determine SSL certificate and key paths
    if environment == "prod":
        # Production environment must use proper SSL cert and key paths
        cert_path = os.getenv("VITE_SSL_CERT_PATH", "ssl/prod-cert.pem")
        key_path = os.getenv("VITE_SSL_KEY_PATH", "ssl/prod-key.pem")
        if not Path(cert_path).exists() or not Path(key_path).exists():
            raise FileNotFoundError(
                f"Production certificates not found."
                f"Make sure the following files exist:\n"
                f"Certificate: {cert_path}\nKey: {key_path}"
            )
        host = "0.0.0.0"  # Allow external traffic
        print(
            f"Running in production mode with provided SSL certificates:\n"
            f" - Certificate: {cert_path}\n - Key: {key_path}"
        )

    elif environment in ["test", "dev"]:
        # Test/Development environments use self-signed certificates
        cert_path = "ssl/cert.pem"
        key_path = "ssl/key.pem"
        host = "127.0.0.1"  # Restrict to localhost
        print(f"Running in {environment} mode with self-signed certificates...")

        # Ensure self-signed certificates exist or generate them
        Path("ssl").mkdir(parents=True, exist_ok=True)
        if not Path(cert_path).exists() or not Path(key_path).exists():
            print(f"Generating self-signed SSL certificate at {cert_path}...")
            ssl_heidi.generate_self_signed_cert(cert_path, key_path)

    else:
        raise ValueError(
            f"Unknown environment: {environment}. "
            f"Must be one of 'prod', 'test', or 'dev'."
        )

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

    # Continuous Integration handling
    if is_ci:
        from multiprocessing import Process
        from time import sleep

        print("CI mode detected: Starting server in a subprocess...")
        server_process = Process(target=run_server)
        server_process.start()
        sleep(5)  # Wait 5 seconds to ensure the server starts without errors
        server_process.terminate()  # Terminate the server (test purposes)
        server_process.join()  # Ensure proper cleanup
        print("CI: Server started and terminated successfully for test validation.")
    else:
        # Run the server normally
        run_server()
