import os

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from psycopg2.extras import RealDictCursor
from database import ensure_user_table, ensure_metric_bind_columns, ensure_product_tables, ensure_interchangeability_metrics, get_db_connection
from auth import validate_production_security, verify_access_token

from routers import project, metric, record, evaluate, user, product, excel_import

app = FastAPI(
    title="精度保持性综合评价系统",
    version="1.0.0",
    docs_url=None if os.getenv("APP_ENV") == "production" else "/docs",
)

cors_origins = [item.strip() for item in os.getenv("CORS_ORIGINS", "http://localhost:5173,http://127.0.0.1:5173").split(",") if item.strip()]

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

PUBLIC_PATHS = {"/health", "/api/users/login"}


@app.middleware("http")
async def authenticate_api_requests(request: Request, call_next):
    if request.method == "OPTIONS" or not request.url.path.startswith("/api") or request.url.path in PUBLIC_PATHS:
        return await call_next(request)
    authorization = request.headers.get("Authorization", "")
    if not authorization.startswith("Bearer "):
        return JSONResponse(status_code=401, content={"status": "error", "message": "请先登录"})
    try:
        request.state.user = verify_access_token(authorization[7:])
    except ValueError as exc:
        return JSONResponse(status_code=401, content={"status": "error", "message": str(exc)})
    user = request.state.user
    if user.get("role") != "admin":
        allowed_user_writes = {
            ("POST", "/api/records"),
            ("POST", "/api/product-records"),
            ("POST", "/api/evaluate"),
        }
        if request.method not in {"GET", "HEAD"} and (request.method, request.url.path) not in allowed_user_writes:
            return JSONResponse(status_code=403, content={"status": "error", "message": "当前账号无权执行该操作"})
        if request.url.path == "/api/users":
            return JSONResponse(status_code=403, content={"status": "error", "message": "当前账号无权查看账号列表"})
    return await call_next(request)

app.include_router(project.router)
app.include_router(metric.router)
app.include_router(record.router)
app.include_router(evaluate.router)
app.include_router(user.router)
app.include_router(product.router)
app.include_router(excel_import.router)


@app.on_event("startup")
def startup_event():
    validate_production_security()
    ensure_user_table()
    ensure_metric_bind_columns()
    ensure_product_tables()
    ensure_interchangeability_metrics()

# ---------------- 系统健康检查 ----------------
@app.get("/health")
def health():
    conn = get_db_connection()
    try:
        cursor = conn.cursor()
        cursor.execute("SELECT 1")
        cursor.fetchone()
        return {"status": "ok"}
    finally:
        conn.close()


@app.get("/api/db-check")
def check_db_connection():
    try:
        conn = get_db_connection()
        cursor = conn.cursor(cursor_factory=RealDictCursor)
        cursor.execute("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'")
        tables = cursor.fetchall()
        cursor.close()
        conn.close()
        return {"status": "success", "message": "数据库连接成功！", "tables_found": [row['table_name'] for row in tables]}
    except Exception as e:
        return {"status": "error", "message": f"数据库连接失败：{str(e)}"}


@app.get("/api/announcements")
def get_announcements(limit: int = 20):
    return {
        "status": "success",
        "data": [
            {
                "id": 1,
                "title": "系统状态通知",
                "content": "精度保持性评估系统运行正常，可进行项目配置、数据采集和综合评估。",
                "type": "notice",
                "created_at": "2026-04-28 09:00:00",
            },
            {
                "id": 2,
                "title": "评估任务提醒",
                "content": "如需开始分析，请先确认设备已绑定指标且存在测试记录。",
                "type": "warning",
                "created_at": "2026-04-28 09:10:00",
            },
        ][:limit],
    }
