from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from sqlalchemy import text

from app.api.data_management import router as data_management_router
from app.api.eval_management import router as eval_management_router
from app.api.monitor import router as monitor_router
from app.api.package_management import router as package_management_router
from app.api.train_management import router as train_management_router
from app.database import Base, engine
from app.models import Category, DataFile, DataPackage, DataPackageFile  # noqa: F401
from app.models.eval_management import EvalRecord  # noqa: F401
from app.models.monitor import MonitorDataPoint, MonitorExperiment  # noqa: F401
from app.models.train_management import SavedModel, TrainTask  # noqa: F401
from app.utils.response import error_response, success_response


def _run_migrations() -> None:
	"""Add new columns to existing tables without dropping data."""
	migrations = [
		"ALTER TABLE train_tasks ADD COLUMN val_package_id BIGINT NULL COMMENT '\u9a8c\u8bc1\u96c6\u6570\u636e\u5305ID' AFTER package_name",
		"ALTER TABLE train_tasks ADD COLUMN val_package_name VARCHAR(255) NULL COMMENT '\u9a8c\u8bc1\u96c6\u6570\u636e\u5305\u540d\u79f0' AFTER val_package_id",
		"ALTER TABLE train_tasks ADD COLUMN epoch_logs JSON NULL COMMENT '\u6bcf\u8f6e\u8bad\u7ec3\u65e5\u5fd7' AFTER val_package_name",
	]
	with engine.connect() as conn:
		for stmt in migrations:
			try:
				conn.execute(text(stmt))
				conn.commit()
			except Exception:
				pass  # Column already exists


def create_app() -> FastAPI:
	# Auto-create any missing tables (safe: uses CREATE TABLE IF NOT EXISTS internally)
	Base.metadata.create_all(bind=engine)

	# Safe column migrations for existing tables
	_run_migrations()

	app = FastAPI(
		title='Thermal Control System API',
		version='0.1.0',
	)

	app.add_middleware(
		CORSMiddleware,
		allow_origins=['*'],
		allow_credentials=True,
		allow_methods=['*'],
		allow_headers=['*'],
	)

	@app.exception_handler(HTTPException)
	async def http_exception_handler(_, exc: HTTPException):
		return JSONResponse(
			status_code=exc.status_code,
			content=error_response(message=str(exc.detail), code=exc.status_code),
		)

	@app.exception_handler(RequestValidationError)
	async def validation_exception_handler(_, exc: RequestValidationError):
		return JSONResponse(
			status_code=422,
			content=error_response(message='参数校验失败', code=422, data=exc.errors()),
		)

	@app.exception_handler(Exception)
	async def unhandled_exception_handler(_, exc: Exception):
		return JSONResponse(
			status_code=500,
			content=error_response(message=f'服务器异常: {exc}', code=500),
		)

	@app.get('/api/health')
	async def health_check():
		return success_response(data={'status': 'ok'}, message='服务正常')

	app.include_router(data_management_router, prefix='/api/data', tags=['数据管理'])
	app.include_router(package_management_router, prefix='/api/packages', tags=['数据包管理'])
	app.include_router(train_management_router, prefix='/api/train', tags=['模型训练'])
	app.include_router(eval_management_router, prefix='/api/eval', tags=['模型评估'])
	app.include_router(monitor_router, prefix='/api/monitor', tags=['实时监控'])

	return app


app = create_app()