import { createContext, useContext, useState } from 'react' import type { ReactNode } from 'react' import { useMutation, useQuery } from '@tanstack/react-query' import type { GroupInviteInfoDto } from '@gruperly/shared' import { ApiError, getInviteInfo, joinViaInvite } from '../../lib/api' type RegisteredAttendee = { fullName: string phone: string | null } type JoinGroupContextValue = { token: string group: GroupInviteInfoDto | undefined invitePending: boolean inviteFailed: boolean firstName: string setFirstName: (value: string) => void lastName: string setLastName: (value: string) => void phone: string setPhone: (value: string) => void email: string setEmail: (value: string) => void errorMessage: string | null registeredAttendee: RegisteredAttendee | null waitlistMessage: string | null submit: () => void isSubmitting: boolean } const JoinGroupContext = createContext(null) export function JoinGroupProvider({ token, children }: { token: string; children: ReactNode }) { const [firstName, setFirstName] = useState('') const [lastName, setLastName] = useState('') const [phone, setPhone] = useState('') const [email, setEmail] = useState('') const [errorMessage, setErrorMessage] = useState(null) const [registeredAttendee, setRegisteredAttendee] = useState(null) const [waitlistMessage, setWaitlistMessage] = useState(null) const inviteQuery = useQuery({ queryKey: ['public-invite', token], queryFn: () => getInviteInfo(token), enabled: Boolean(token), retry: 1, }) const joinMutation = useMutation({ mutationFn: () => joinViaInvite(token, { firstName: firstName.trim(), lastName: lastName.trim(), phone: phone.trim(), email: email.trim() || undefined, }), onSuccess: (data) => { setErrorMessage(null) if (data.status === 'waitlisted') { setRegisteredAttendee(null) setWaitlistMessage(data.message) return } setWaitlistMessage(null) setRegisteredAttendee({ fullName: data.attendee?.fullName ?? `${firstName.trim()} ${lastName.trim()}`.trim(), phone: data.attendee?.phone ?? null, }) }, onError: (error: unknown) => { if (error instanceof ApiError) { if (error.problem?.code === 'attendee_already_registered') { setErrorMessage( 'Ya te encuentras registrado en este grupo con ese número de teléfono. El profesor ya tiene tus datos.', ) return } setErrorMessage(error.message || 'Error al procesar la inscripción.') return } if (error instanceof Error) { setErrorMessage(error.message) return } setErrorMessage('Ocurrió un error inesperado. Por favor, intenta de nuevo.') }, }) const submit = () => { setErrorMessage(null) if (!firstName.trim() || !lastName.trim() || !phone.trim()) { setErrorMessage('Por favor completa los campos requeridos (Nombre, Apellido y Teléfono).') return } joinMutation.mutate() } const value: JoinGroupContextValue = { token, group: inviteQuery.data, invitePending: inviteQuery.isPending, inviteFailed: inviteQuery.isError, firstName, setFirstName, lastName, setLastName, phone, setPhone, email, setEmail, errorMessage, registeredAttendee, waitlistMessage, submit, isSubmitting: joinMutation.isPending, } return {children} } export function useJoinGroup() { const context = useContext(JoinGroupContext) if (!context) { throw new Error('useJoinGroup debe usarse dentro de ') } return context }