"""Cards management router.""" import json from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query, Request from sqlalchemy.orm import Session from sqlalchemy import func from datetime import datetime, timezone from app.auth import get_current_user, AdminUser from app.database import get_db from app.models.db_models import CardLog, SystemSetting from app.services import airwallex_service from app.services.audit_log import create_card_log, create_audit_log router = APIRouter(prefix="/api/cards", tags=["cards"]) @router.get("") def list_cards( page_num: int = Query(0, ge=0), page_size: int = Query(20, ge=1, le=100), cardholder_id: Optional[str] = None, status: Optional[str] = None, db: Session = Depends(get_db), user: AdminUser = Depends(get_current_user), ): """List cards with optional filters.""" return airwallex_service.list_cards(db, page_num, page_size, cardholder_id, status) @router.post("") def create_card( request: Request, card_data: dict, db: Session = Depends(get_db), user: AdminUser = Depends(get_current_user), ): """Create a new card.""" # Check daily limit today_start = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0) today_count = ( db.query(func.count(CardLog.id)) .filter(CardLog.action == "create_card", CardLog.status == "success", CardLog.created_at >= today_start) .scalar() ) or 0 limit_setting = db.query(SystemSetting).filter(SystemSetting.key == "daily_card_limit").first() daily_limit = int(limit_setting.value) if limit_setting else 100 if today_count >= daily_limit: raise HTTPException(status_code=429, detail=f"Daily card creation limit ({daily_limit}) reached") try: result = airwallex_service.create_card(db, card_data) create_card_log( db, action="create_card", status="success", operator=user.username, card_id=result.get("card_id", result.get("id", "")), cardholder_id=card_data.get("cardholder_id", ""), request_data=json.dumps(card_data), response_data=json.dumps(result, default=str), ) create_audit_log( db, action="create_card", resource_type="card", resource_id=result.get("card_id", result.get("id", "")), operator=user.username, ip_address=request.client.host if request.client else "", details=f"Created card for cardholder {card_data.get('cardholder_id', '')}", ) return result except Exception as e: create_card_log( db, action="create_card", status="failed", operator=user.username, cardholder_id=card_data.get("cardholder_id", ""), request_data=json.dumps(card_data), response_data=str(e), ) raise HTTPException(status_code=400, detail=str(e)) @router.get("/{card_id}") def get_card( card_id: str, db: Session = Depends(get_db), user: AdminUser = Depends(get_current_user), ): """Get card by ID.""" try: return airwallex_service.get_card(db, card_id) except Exception as e: raise HTTPException(status_code=404, detail=str(e)) @router.get("/{card_id}/details") def get_card_details( card_id: str, request: Request, db: Session = Depends(get_db), user: AdminUser = Depends(get_current_user), ): """Get sensitive card details (card number, CVV, expiry).""" create_audit_log( db, action="view_card_details", resource_type="card", resource_id=card_id, operator=user.username, ip_address=request.client.host if request.client else "", ) try: return airwallex_service.get_card_details(db, card_id) except Exception as e: raise HTTPException(status_code=404, detail=str(e)) @router.put("/{card_id}") def update_card( card_id: str, update_data: dict, request: Request, db: Session = Depends(get_db), user: AdminUser = Depends(get_current_user), ): """Update card attributes.""" try: result = airwallex_service.update_card(db, card_id, update_data) create_audit_log( db, action="update_card", resource_type="card", resource_id=card_id, operator=user.username, ip_address=request.client.host if request.client else "", details=json.dumps(update_data), ) return result except Exception as e: raise HTTPException(status_code=400, detail=str(e))