from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from datetime import datetime from typing import List from ..database import get_db from ..models import User, DealerApplication, DealerInfo from ..models.dealer import generate_dealer_code from ..schemas import ( DealerApplicationCreate, DealerApplicationResponse, DealerApplicationReject, DealerInfoResponse, DealerPublicInfo, ) from .auth import get_current_user from .notification import notify_dealer_approved, notify_dealer_rejected router = APIRouter(prefix="/dealer", tags=["dealer"]) @router.post("/apply", response_model=DealerApplicationResponse) def apply_dealer( application: DealerApplicationCreate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Submit a dealer application""" # Check if user already has a pending or approved application existing = db.query(DealerApplication).filter( DealerApplication.user_id == current_user.id, DealerApplication.status.in_(["pending", "approved"]) ).first() if existing: if existing.status == "approved": raise HTTPException(status_code=400, detail="You are already a dealer") raise HTTPException(status_code=400, detail="You already have a pending application") # Check if user is already a dealer if current_user.is_dealer: raise HTTPException(status_code=400, detail="You are already a dealer") # Create new application new_application = DealerApplication( user_id=current_user.id, business_name=application.business_name, business_number=application.business_number, real_name=application.real_name, id_number_encrypted=application.id_number, # TODO: Encrypt this properly phone=application.phone, bank_name=application.bank_name, bank_account=application.bank_account, account_holder=application.account_holder, photo_url=application.photo_url, status="pending" ) db.add(new_application) db.commit() db.refresh(new_application) return new_application @router.get("/my-application", response_model=DealerApplicationResponse) def get_my_application( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Get current user's dealer application""" application = db.query(DealerApplication).filter( DealerApplication.user_id == current_user.id ).order_by(DealerApplication.applied_at.desc()).first() if not application: raise HTTPException(status_code=404, detail="No application found") return application @router.get("/my-info", response_model=DealerInfoResponse) def get_my_dealer_info( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Get current user's dealer info (if approved)""" if not current_user.is_dealer: raise HTTPException(status_code=403, detail="You are not a dealer") dealer_info = db.query(DealerInfo).filter( DealerInfo.user_id == current_user.id ).first() if not dealer_info: raise HTTPException(status_code=404, detail="Dealer info not found") return dealer_info @router.get("/list", response_model=List[DealerPublicInfo]) def list_dealers( db: Session = Depends(get_db) ): """Get list of active dealers (public info only)""" dealers = db.query(DealerInfo).filter( DealerInfo.is_active == True ).all() return dealers # Admin endpoints @router.get("/admin/applications", response_model=List[DealerApplicationResponse]) def get_applications( status_filter: str = None, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """[Admin] Get all dealer applications""" if not current_user.is_admin: raise HTTPException(status_code=403, detail="Admin access required") query = db.query(DealerApplication) if status_filter: query = query.filter(DealerApplication.status == status_filter) applications = query.order_by(DealerApplication.applied_at.desc()).all() return applications @router.put("/admin/applications/{application_id}/approve", response_model=DealerInfoResponse) def approve_application( application_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """[Admin] Approve a dealer application""" if not current_user.is_admin: raise HTTPException(status_code=403, detail="Admin access required") application = db.query(DealerApplication).filter( DealerApplication.id == application_id ).first() if not application: raise HTTPException(status_code=404, detail="Application not found") if application.status != "pending": raise HTTPException(status_code=400, detail="Application is not pending") # Generate unique dealer code dealer_code = generate_dealer_code() while db.query(DealerInfo).filter(DealerInfo.dealer_code == dealer_code).first(): dealer_code = generate_dealer_code() # Create dealer info dealer_info = DealerInfo( user_id=application.user_id, dealer_code=dealer_code, business_name=application.business_name, real_name=application.real_name, phone=application.phone, photo_url=application.photo_url, bank_name=application.bank_name, bank_account=application.bank_account, account_holder=application.account_holder, ) # Update application status application.status = "approved" application.approved_at = datetime.utcnow() # Update user is_dealer flag user = db.query(User).filter(User.id == application.user_id).first() user.is_dealer = True db.add(dealer_info) db.commit() db.refresh(dealer_info) # TODO: Generate dealer card image here # dealer_info.dealer_card_url = generate_dealer_card(dealer_info) # db.commit() # Send notification to user about dealer approval notify_dealer_approved(db, application.user_id, dealer_code) return dealer_info @router.put("/admin/applications/{application_id}/reject") def reject_application( application_id: int, reject_data: DealerApplicationReject, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """[Admin] Reject a dealer application""" if not current_user.is_admin: raise HTTPException(status_code=403, detail="Admin access required") application = db.query(DealerApplication).filter( DealerApplication.id == application_id ).first() if not application: raise HTTPException(status_code=404, detail="Application not found") if application.status != "pending": raise HTTPException(status_code=400, detail="Application is not pending") application.status = "rejected" application.rejected_reason = reject_data.reason db.commit() # Send notification to user about dealer rejection notify_dealer_rejected(db, application.user_id, reject_data.reason) return {"message": "Application rejected", "reason": reject_data.reason} @router.get("/admin/dealers", response_model=List[DealerInfoResponse]) def get_all_dealers( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """[Admin] Get all dealers with full info""" if not current_user.is_admin: raise HTTPException(status_code=403, detail="Admin access required") dealers = db.query(DealerInfo).all() return dealers @router.put("/admin/dealers/{dealer_id}/toggle-active") def toggle_dealer_active( dealer_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """[Admin] Toggle dealer active status""" if not current_user.is_admin: raise HTTPException(status_code=403, detail="Admin access required") dealer = db.query(DealerInfo).filter(DealerInfo.id == dealer_id).first() if not dealer: raise HTTPException(status_code=404, detail="Dealer not found") dealer.is_active = not dealer.is_active # Also update user's is_dealer status user = db.query(User).filter(User.id == dealer.user_id).first() if user: user.is_dealer = dealer.is_active db.commit() return {"message": f"Dealer {'activated' if dealer.is_active else 'deactivated'}", "is_active": dealer.is_active}