import time import json import uuid from fastapi import APIRouter, HTTPException, Depends, Header from pydantic import BaseModel from typing import Optional, Any, Dict from app.models.user import get_db_connection from app.api.v1.auth import get_current_user, decode_token router = APIRouter() class SaveProjectRequest(BaseModel): name: str data_json: str class SaveTempProjectRequest(BaseModel): data_json: str def get_optional_user(authorization: Optional[str] = Header(None)) -> Optional[dict]: if authorization and authorization.startswith("Bearer "): token = authorization.split(" ")[1] return decode_token(token) return None @router.post("/temp") async def save_temp_project(req: SaveTempProjectRequest, current_user: Optional[dict] = Depends(get_optional_user)): user_id = current_user["user_id"] if current_user else "anonymous" conn = get_db_connection() cursor = conn.cursor() size_bytes = len(req.data_json.encode("utf-8")) now = time.time() temp_id = f"temp_{user_id}" cursor.execute(""" INSERT INTO projects (id, user_id, name, data_json, is_temp, size_bytes, updated_at) VALUES (?, ?, 'Dự án tạm chưa lưu', ?, 1, ?, ?) ON CONFLICT(id) DO UPDATE SET data_json = excluded.data_json, size_bytes = excluded.size_bytes, updated_at = excluded.updated_at """, (temp_id, user_id, req.data_json, size_bytes, now)) conn.commit() conn.close() return {"message": "Đã lưu dự án tạm tự động", "updated_at": now} @router.get("/temp") async def get_temp_project(current_user: Optional[dict] = Depends(get_optional_user)): user_id = current_user["user_id"] if current_user else "anonymous" temp_id = f"temp_{user_id}" conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT data_json, updated_at FROM projects WHERE id = ? AND is_temp = 1", (temp_id,)) row = cursor.fetchone() conn.close() if not row: return {"has_temp": False} return { "has_temp": True, "data_json": row["data_json"], "updated_at": row["updated_at"] } @router.post("/cloud") async def save_cloud_project(req: SaveProjectRequest, current_user: dict = Depends(get_current_user)): user_id = current_user["user_id"] conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT storage_limit_mb FROM user_quotas WHERE user_id = ?", (user_id,)) quota_row = cursor.fetchone() storage_limit_mb = quota_row["storage_limit_mb"] if quota_row else 500 cursor.execute("SELECT SUM(size_bytes) as total_used FROM projects WHERE user_id = ? AND is_temp = 0", (user_id,)) used_row = cursor.fetchone() used_bytes = used_row["total_used"] if used_row and used_row["total_used"] else 0 new_size_bytes = len(req.data_json.encode("utf-8")) max_bytes = storage_limit_mb * 1024 * 1024 if used_bytes + new_size_bytes > max_bytes: conn.close() raise HTTPException( status_code=400, detail=f"Dung lượng dự án vượt quá hạn mức Quota ({storage_limit_mb}MB). Vui lòng dọn dẹp hoặc nâng cấp tài khoản." ) project_id = str(uuid.uuid4()) now = time.time() cursor.execute(""" INSERT INTO projects (id, user_id, name, data_json, is_temp, size_bytes, updated_at) VALUES (?, ?, ?, ?, 0, ?, ?) """, (project_id, user_id, req.name, req.data_json, new_size_bytes, now)) temp_id = f"temp_{user_id}" cursor.execute("DELETE FROM projects WHERE id = ? AND is_temp = 1", (temp_id,)) conn.commit() conn.close() return { "message": "Đã lưu dự án lên Cloud thành công!", "project_id": project_id } @router.get("/cloud") async def list_cloud_projects(current_user: dict = Depends(get_current_user)): user_id = current_user["user_id"] conn = get_db_connection() cursor = conn.cursor() cursor.execute(""" SELECT id, name, size_bytes, updated_at FROM projects WHERE user_id = ? AND is_temp = 0 ORDER BY updated_at DESC """, (user_id,)) rows = cursor.fetchall() conn.close() return [ { "id": r["id"], "name": r["name"], "size_mb": round(r["size_bytes"] / (1024 * 1024), 2), "updated_at": r["updated_at"] } for r in rows ] @router.get("/cloud/{project_id}") async def get_cloud_project(project_id: str, current_user: dict = Depends(get_current_user)): user_id = current_user["user_id"] conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT name, data_json FROM projects WHERE id = ? AND user_id = ? AND is_temp = 0", (project_id, user_id)) row = cursor.fetchone() conn.close() if not row: raise HTTPException(status_code=404, detail="Không tìm thấy dự án") return { "id": project_id, "name": row["name"], "data_json": row["data_json"] } @router.delete("/cloud/{project_id}") async def delete_cloud_project(project_id: str, current_user: dict = Depends(get_current_user)): user_id = current_user["user_id"] conn = get_db_connection() cursor = conn.cursor() cursor.execute("DELETE FROM projects WHERE id = ? AND user_id = ? AND is_temp = 0", (project_id, user_id)) conn.commit() conn.close() return {"success": True, "message": "Đã xóa dự án thành công"} @router.put("/cloud/{project_id}") async def update_cloud_project(project_id: str, req: SaveProjectRequest, current_user: dict = Depends(get_current_user)): user_id = current_user["user_id"] conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT id FROM projects WHERE id = ? AND user_id = ? AND is_temp = 0", (project_id, user_id)) exists = cursor.fetchone() if not exists: conn.close() raise HTTPException(status_code=404, detail="Không tìm thấy dự án để cập nhật") new_size_bytes = len(req.data_json.encode("utf-8")) now = time.time() cursor.execute(""" UPDATE projects SET name = ?, data_json = ?, size_bytes = ?, updated_at = ? WHERE id = ? AND user_id = ? """, (req.name, req.data_json, new_size_bytes, now, project_id, user_id)) conn.commit() conn.close() return {"success": True, "message": "Đã cập nhật dự án thành công"}