import { z } from 'zod' import { errorResult, handleServiceError, type ServiceCallOptions, type ServiceResult, shouldBubbleErrorToParent, successResult, } from '@/services/errorHandler' import { unwrapApiDataUnknown, unwrapApiPayload } from '@/helpers/listResponse' import { ANALYTICS_EVENTS, trackAnalyticsEventOnce } from '@/lib/analytics' import { API_ROUTES } from '@/services/config' import axiosInstance from '@/config/axios' import { texts } from '@/texts' export interface MyIdentityVerification { id: string status: 'pending' | 'verified' | 'rejected' nationalCode: string | null contractVersion?: string | null contractAcceptedAt?: string | null contractAcceptanceId?: string | null reason?: { code: string; label: string } | null rejectionReason?: string | null createdAt: string reviewedAt?: string | null } export interface IdentityRejectionReason { id: number code: string label: string sortOrder: number } export interface RequestHostContractOtpPayload { nationalCode: string contractAccepted: true contractVersion: string } const identityVerificationSchema = z.object({ id: z.string().min(1), status: z.enum(['pending', 'verified', 'rejected']), nationalCode: z.string().nullable().optional(), contractVersion: z.string().nullable().optional(), contractAcceptedAt: z.string().nullable().optional(), contractAcceptanceId: z.string().nullable().optional(), reason: z.object({ code: z.string(), label: z.string() }).nullable().optional(), rejectionReason: z.string().nullable().optional(), createdAt: z.string(), reviewedAt: z.string().nullable().optional(), }) const rejectionReasonSchema = z.object({ id: z.number(), code: z.string(), label: z.string(), sortOrder: z.number(), }) const otpRequestedSchema = z.object({ purpose: z.literal('host_contract'), expiresIn: z.number(), contractVersion: z.string(), }) export const GET_MY_IDENTITY_VERIFICATION = async (options?: ServiceCallOptions): Promise> => { try { const res = await axiosInstance.get('identity/verifications/me') const payload = unwrapApiDataUnknown(res.data) const latest: unknown = Array.isArray(payload) ? payload[0] : payload if (!latest || typeof latest !== 'object' || !('id' in latest)) return successResult(null) const parsed = identityVerificationSchema.safeParse(latest) if (!parsed.success) throw new Error(texts.common.invalidServerResponse) return successResult({ ...parsed.data, nationalCode: parsed.data.nationalCode ?? null, }) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } export const REQUEST_HOST_CONTRACT_OTP = async ( data: RequestHostContractOtpPayload, options?: ServiceCallOptions ): Promise> => { try { const res = await axiosInstance.post(API_ROUTES.IDENTITY.REQUEST_OTP, data) const parsed = otpRequestedSchema.safeParse(unwrapApiPayload(res.data)) if (!parsed.success) throw new Error(texts.common.invalidServerResponse) return successResult(parsed.data) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } export const CONFIRM_HOST_CONTRACT_OTP = async ( code: string, options?: ServiceCallOptions ): Promise> => { try { const res = await axiosInstance.post(API_ROUTES.IDENTITY.CONFIRM_OTP, { code }) const parsed = identityVerificationSchema.safeParse(unwrapApiPayload(res.data)) if (!parsed.success) throw new Error(texts.common.invalidServerResponse) trackAnalyticsEventOnce(ANALYTICS_EVENTS.IDENTITY_VERIFICATION_SUBMITTED, parsed.data.id, { verification_id: parsed.data.id, verification_status: parsed.data.status, }) return successResult({ ...parsed.data, nationalCode: parsed.data.nationalCode ?? null, }) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } export const GET_IDENTITY_REJECTION_REASONS = async (options?: ServiceCallOptions): Promise> => { try { const res = await axiosInstance.get(API_ROUTES.IDENTITY.REJECTION_REASONS) const payload = unwrapApiDataUnknown(res.data) const parsed = z.array(rejectionReasonSchema).safeParse(Array.isArray(payload) ? payload : []) if (!parsed.success) throw new Error(texts.common.invalidServerResponse) return successResult(parsed.data) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } }