File size: 5,749 Bytes
ecb9f70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
"""User profile synchronization endpoints."""

from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import Response
from pydantic import BaseModel

from src.api.auth import require_auth
from src.api.deps import get_storage
from src.storage import BodhiStorage

router = APIRouter(prefix="/api/users", tags=["users"])


class UserSyncResponse(BaseModel):
    user_id: str
    clerk_user_id: str


class UserStatusResponse(BaseModel):
    user_id: str
    clerk_user_id: str
    has_resume: bool


@router.post("/me", response_model=UserSyncResponse)
async def upsert_current_user(
    clerk_user_id: str = Depends(require_auth),
    storage: BodhiStorage = Depends(get_storage),
):
    user_id = storage.ensure_user_profile_for_clerk(clerk_user_id)
    return UserSyncResponse(user_id=user_id, clerk_user_id=clerk_user_id)


@router.get("/me", response_model=UserSyncResponse)
async def get_current_user(
    clerk_user_id: str = Depends(require_auth),
    storage: BodhiStorage = Depends(get_storage),
):
    user_id = storage.get_user_profile_id_by_clerk_user_id(clerk_user_id)
    if not user_id:
        user_id = storage.ensure_user_profile_for_clerk(clerk_user_id)
    return UserSyncResponse(user_id=user_id, clerk_user_id=clerk_user_id)


@router.get("/me/status", response_model=UserStatusResponse)
async def get_current_user_status(
    clerk_user_id: str = Depends(require_auth),
    storage: BodhiStorage = Depends(get_storage),
):
    status = storage.get_user_profile_status_by_clerk_user_id(clerk_user_id)
    if not status:
        user_id = storage.ensure_user_profile_for_clerk(clerk_user_id)
        return UserStatusResponse(
            user_id=user_id,
            clerk_user_id=clerk_user_id,
            has_resume=False,
        )
    user_id, has_resume = status
    return UserStatusResponse(
        user_id=user_id,
        clerk_user_id=clerk_user_id,
        has_resume=has_resume,
    )


from datetime import datetime

class InterviewHistoryItem(BaseModel):
    session_id: str
    target_company: str
    target_role: str
    overall_score: float | None = None
    started_at: datetime
    ended_at: datetime | None = None

class UserProfileResponse(BaseModel):
    clerk_user_id: str
    has_resume: bool
    resume_data: dict | None = None
    resume_file_name: str | None = None
    interview_history: list[InterviewHistoryItem]
    full_name: str | None = None
    experience_level: str | None = None

class UpdateNameRequest(BaseModel):
    full_name: str

class UpdateExperienceRequest(BaseModel):
    experience_level: str

@router.get("/me/resume/download")
async def download_resume(
    clerk_user_id: str = Depends(require_auth),
    storage: BodhiStorage = Depends(get_storage),
):
    content, filename = storage.get_user_resume_file(clerk_user_id)
    if not content:
        raise HTTPException(status_code=404, detail="No resume available to download.")
    return Response(content, media_type="application/octet-stream", headers={
        "Content-Disposition": f'attachment; filename="{filename or "resume.pdf"}"'
    })

@router.get("/me/profile", response_model=UserProfileResponse)
async def get_full_user_profile(
    clerk_user_id: str = Depends(require_auth),
    storage: BodhiStorage = Depends(get_storage),
):
    # Get user profile status to find user_id and has_resume
    status = storage.get_user_profile_status_by_clerk_user_id(clerk_user_id)
    if not status:
        user_id = storage.ensure_user_profile_for_clerk(clerk_user_id)
        has_resume = False
    else:
        user_id, has_resume = status

    # Get resume profile data
    resume_data = None
    resume_file_name = None
    if has_resume:
        full_profile = storage.get_user_profile(user_id)
        if full_profile and getattr(full_profile, "get", None):
            resume_data = full_profile.get("professional_summary")
            resume_file_name = full_profile.get("resume_file_name")

    # Get interview history
    history = storage.get_user_interview_history(clerk_user_id)
    
    # Get full name + experience
    full_name = storage.get_user_full_name(clerk_user_id)
    experience_level = storage.get_user_experience_level(clerk_user_id)
    
    return UserProfileResponse(
        clerk_user_id=clerk_user_id,
        has_resume=has_resume,
        resume_data=resume_data,
        resume_file_name=resume_file_name,
        interview_history=history,
        full_name=full_name,
        experience_level=experience_level,
    )


@router.put("/me/name")
async def update_user_name(
    body: UpdateNameRequest,
    clerk_user_id: str = Depends(require_auth),
    storage: BodhiStorage = Depends(get_storage),
):
    """Update the user's full name in the profile table."""
    # Ensure user profile exists
    storage.ensure_user_profile_for_clerk(clerk_user_id)
    
    # Update the name
    success = storage.update_user_full_name(clerk_user_id, body.full_name)
    
    if not success:
        raise HTTPException(status_code=400, detail="Failed to update name")
    
    return {"success": True, "full_name": body.full_name}

@router.put("/me/experience")
async def update_user_experience(
    body: UpdateExperienceRequest,
    clerk_user_id: str = Depends(require_auth),
    storage: BodhiStorage = Depends(get_storage),
):
    """Update the user's explicit experience level in the profile table."""
    storage.ensure_user_profile_for_clerk(clerk_user_id)
    success = storage.update_user_experience_level(clerk_user_id, body.experience_level)
    if not success:
        raise HTTPException(status_code=400, detail="Failed to update experience level")
    return {"success": True, "experience_level": body.experience_level}