from fastapi import APIRouter, Depends, Query
from fastapi.responses import StreamingResponse
from openpyxl import Workbook
from sqlalchemy.orm import Session

from app.api.deps import require_roles
from app.core.paths import data_path
from app.db.session import get_db
from app.models import AdminUser, OperationLog
from app.schemas.log import OperationLogPage
from app.services.logs import HIGH_RISK_LOG_RETENTION_DAYS, LOG_RETENTION_DAYS, cleanup_expired_logs, format_log

router = APIRouter()


@router.get("", response_model=OperationLogPage)
def list_logs(
    action: str | None = Query(default=None),
    object_type: str | None = Query(default=None),
    risk: str | None = Query(default=None),
    keyword: str | None = Query(default=None),
    page: int = Query(default=1, ge=1),
    page_size: int = Query(default=20, ge=1, le=100),
    db: Session = Depends(get_db),
    _: AdminUser = Depends(require_roles("system_admin", "certificate_admin", "readonly")),
) -> dict[str, object]:
    items = _query_logs(db, action, object_type, risk, keyword)
    total = len(items)
    total_pages = max(1, (total + page_size - 1) // page_size)
    page = min(page, total_pages)
    start = (page - 1) * page_size
    return {
        "items": items[start:start + page_size],
        "total": total,
        "page": page,
        "page_size": page_size,
        "total_pages": total_pages,
    }


@router.get("/export")
def export_logs(
    action: str | None = Query(default=None),
    object_type: str | None = Query(default=None),
    risk: str | None = Query(default=None),
    keyword: str | None = Query(default=None),
    db: Session = Depends(get_db),
    _: AdminUser = Depends(require_roles("system_admin", "certificate_admin", "readonly")),
) -> StreamingResponse:
    items = _query_logs(db, action, object_type, risk, keyword)
    workbook = Workbook()
    sheet = workbook.active
    sheet.title = "\u64cd\u4f5c\u65e5\u5fd7"
    sheet.append(["\u65f6\u95f4", "\u64cd\u4f5c\u4ebaID", "\u64cd\u4f5c", "\u5bf9\u8c61", "\u5bf9\u8c61ID", "\u98ce\u9669\u7b49\u7ea7", "\u6458\u8981", "\u8be6\u60c5"])
    for item in items:
        sheet.append([
            item.get("created_at"),
            item.get("admin_user_id"),
            item.get("action_label"),
            item.get("object_label"),
            item.get("object_id"),
            item.get("risk_label"),
            item.get("summary"),
            item.get("detail_json"),
        ])
    for column in "ABCDEFGH":
        sheet.column_dimensions[column].width = 22 if column != "H" else 60
    export_path = data_path("exports") / "operation-logs.xlsx"
    workbook.save(export_path)
    file_handle = export_path.open("rb")
    return StreamingResponse(
        file_handle,
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": 'attachment; filename="operation-logs.xlsx"'},
    )


@router.post("/cleanup")
def cleanup_logs(
    db: Session = Depends(get_db),
    _: AdminUser = Depends(require_roles("system_admin", "certificate_admin")),
) -> dict[str, int]:
    removed = cleanup_expired_logs(db)
    db.commit()
    return {
        "removed": removed,
        "normal_retention_days": LOG_RETENTION_DAYS,
        "high_risk_retention_days": HIGH_RISK_LOG_RETENTION_DAYS,
    }


def _query_logs(
    db: Session,
    action: str | None,
    object_type: str | None,
    risk: str | None,
    keyword: str | None,
) -> list[dict[str, object]]:
    query = db.query(OperationLog).order_by(OperationLog.id.desc())
    cleanup_expired_logs(db)
    db.commit()
    if action:
        query = query.filter(OperationLog.action == action)
    if object_type:
        query = query.filter(OperationLog.object_type == object_type)
    items = [format_log(item) for item in query.limit(500).all()]
    if risk:
        items = [item for item in items if item["risk"] == risk]
    if keyword:
        word = keyword.strip().lower()
        items = [
            item for item in items
            if word in " ".join(str(item.get(key, "")) for key in ["object_id", "summary", "detail_json", "action_label", "object_label"]).lower()
        ]
    return items[:200]
