from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from sqlalchemy import desc from typing import Optional from app.db.session import get_db from app.core.deps import get_current_user, get_current_developer from app.models.user import User from app.models.carbon_project import CarbonProject from app.models.carbon_offset import CarbonOffset from app.schemas.carbon_project import ( CarbonProjectCreate, CarbonProjectResponse, CarbonProjectUpdate, CarbonProjectListResponse ) router = APIRouter() @router.post("/", response_model=CarbonProjectResponse) def create_project( project: CarbonProjectCreate, current_user: User = Depends(get_current_developer), db: Session = Depends(get_db) ): """Create a new carbon offset project (Developer only)""" # Validate project dates if project.start_date >= project.end_date: raise HTTPException( status_code=400, detail="Start date must be before end date" ) # Create project db_project = CarbonProject( **project.dict(), developer_id=current_user.id ) db.add(db_project) db.commit() db.refresh(db_project) # Create initial carbon offsets db_offset = CarbonOffset( serial_number=f"CO{db_project.id}-{project.total_credits_available}", vintage_year=project.start_date.year, quantity=project.total_credits_available, project_id=db_project.id ) db.add(db_offset) db.commit() return db_project @router.get("/", response_model=CarbonProjectListResponse) def list_projects( page: int = Query(1, ge=1), page_size: int = Query(10, ge=1, le=100), project_type: Optional[str] = None, verification_status: Optional[str] = None, db: Session = Depends(get_db) ): """List all active carbon offset projects""" query = db.query(CarbonProject).filter(CarbonProject.is_active == True) if project_type: query = query.filter(CarbonProject.project_type == project_type) if verification_status: query = query.filter(CarbonProject.verification_status == verification_status) # Get total count total = query.count() # Apply pagination projects = query.order_by(desc(CarbonProject.created_at)).offset( (page - 1) * page_size ).limit(page_size).all() return CarbonProjectListResponse( projects=projects, total=total, page=page, page_size=page_size ) @router.get("/my-projects", response_model=CarbonProjectListResponse) def get_my_projects( page: int = Query(1, ge=1), page_size: int = Query(10, ge=1, le=100), current_user: User = Depends(get_current_developer), db: Session = Depends(get_db) ): """Get projects created by the current developer""" query = db.query(CarbonProject).filter(CarbonProject.developer_id == current_user.id) total = query.count() projects = query.order_by(desc(CarbonProject.created_at)).offset( (page - 1) * page_size ).limit(page_size).all() return CarbonProjectListResponse( projects=projects, total=total, page=page, page_size=page_size ) @router.get("/{project_id}", response_model=CarbonProjectResponse) def get_project(project_id: int, db: Session = Depends(get_db)): """Get a specific project by ID""" project = db.query(CarbonProject).filter( CarbonProject.id == project_id, CarbonProject.is_active == True ).first() if not project: raise HTTPException(status_code=404, detail="Project not found") return project @router.put("/{project_id}", response_model=CarbonProjectResponse) def update_project( project_id: int, project_update: CarbonProjectUpdate, current_user: User = Depends(get_current_developer), db: Session = Depends(get_db) ): """Update a project (Developer only - own projects)""" project = db.query(CarbonProject).filter( CarbonProject.id == project_id, CarbonProject.developer_id == current_user.id ).first() if not project: raise HTTPException(status_code=404, detail="Project not found") # Update project fields update_data = project_update.dict(exclude_unset=True) for field, value in update_data.items(): setattr(project, field, value) db.commit() db.refresh(project) return project @router.delete("/{project_id}") def delete_project( project_id: int, current_user: User = Depends(get_current_developer), db: Session = Depends(get_db) ): """Delete a project (Developer only - own projects)""" project = db.query(CarbonProject).filter( CarbonProject.id == project_id, CarbonProject.developer_id == current_user.id ).first() if not project: raise HTTPException(status_code=404, detail="Project not found") # Soft delete - mark as inactive project.is_active = False db.commit() return {"message": "Project deleted successfully"}