import { clientFetch } from '@/lib/api/client';
import { ApiError } from '@/lib/api/errors';
import { unwrap, type ApiEnvelope } from '@/lib/api/types';
import type {
  AvatarUploadResult,
  CustomerProfile,
  CustomerProfileDto,
  NurseProfile,
  NurseProfileDto,
  ProfilesApi,
  UpsertCustomerProfileInput,
  UpsertNurseProfileInput,
} from '../types';

const BASE = '/api/v1';

// A caller with no profile yet gets a 404 from the GET — map that to `null` (an empty form),
// not an error. Any other status propagates.
async function orNull<T>(promise: Promise<T>): Promise<T | null> {
  try {
    return await promise;
  } catch (error) {
    if (error instanceof ApiError && error.status === 404) return null;
    throw error;
  }
}

/** REQ-006 (delivered): both profile DTOs now carry `avatarUrl`; the customer DTO also carries `preferredLanguage`. */
interface NurseProfileWire extends NurseProfileDto {
  avatarUrl: string | null;
}
interface CustomerProfileWire extends CustomerProfileDto {
  avatarUrl: string | null;
  preferredLanguage: string | null;
}

function toNurseProfile(dto: NurseProfileWire): NurseProfile {
  return { ...dto, avatarUrl: dto.avatarUrl ?? null };
}
// The customer name lives on `/me` (REQ-007 design), not on `CustomerProfileDto` — the profile screen
// sources first/last name from `useMe`. Here we carry the served `preferredLanguage`; name stays null.
function toCustomerProfile(dto: CustomerProfileWire): CustomerProfile {
  return { ...dto, firstName: null, lastName: null, preferredLanguage: dto.preferredLanguage ?? null };
}

/**
 * Real HTTP implementation of the ProfilesApi seam (b3 action-style routes). PRIMARY once
 * USE_PROFILES_MOCK is false (refinement-phase-4; REQ-006/007 delivered). Avatar upload posts multipart
 * to the b3 `nurse_profiles/avatar` route (the JSON-only default is bypassed for `FormData` bodies —
 * see `lib/api/client.ts`); the customer name/language reach the server via the upsert body.
 */
export const profilesClientApi: ProfilesApi = {
  getCustomerProfile: async () =>
    orNull(
      clientFetch<ApiEnvelope<CustomerProfileWire>>(`${BASE}/customer_profiles/me`).then((env) =>
        toCustomerProfile(unwrap(env)),
      ),
    ),

  upsertCustomerProfile: async (input: UpsertCustomerProfileInput) =>
    toCustomerProfile(
      unwrap(
        await clientFetch<ApiEnvelope<CustomerProfileWire>>(`${BASE}/customer_profiles/upsert`, {
          method: 'POST',
          body: JSON.stringify({
            defaultEmergencyContactName: input.defaultEmergencyContactName,
            defaultEmergencyContactPhone: input.defaultEmergencyContactPhone,
            // REQ-007 (delivered): name + preferred language are accepted on the upsert command.
            firstName: input.firstName ?? null,
            lastName: input.lastName ?? null,
            preferredLanguage: input.preferredLanguage ?? null,
          }),
        }),
      ),
    ),

  getNurseProfile: async () =>
    orNull(
      clientFetch<ApiEnvelope<NurseProfileWire>>(`${BASE}/nurse_profiles/me`).then((env) => toNurseProfile(unwrap(env))),
    ),

  upsertNurseProfile: async (input: UpsertNurseProfileInput) =>
    toNurseProfile(
      unwrap(
        await clientFetch<ApiEnvelope<NurseProfileWire>>(`${BASE}/nurse_profiles/upsert`, {
          method: 'POST',
          body: JSON.stringify({
            bio: input.bio,
            yearsOfExperience: input.yearsOfExperience,
            educationLevel: input.educationLevel,
            educationField: input.educationField,
            specializationsJson: input.specializationsJson,
          }),
        }),
      ),
    ),

  // REQ-006 (delivered): only the nurse profile screen uploads an avatar today; it persists immediately
  // via the dedicated multipart route and the returned URL is echoed for display + read back on reload.
  uploadAvatar: async (file: File): Promise<AvatarUploadResult> => {
    const form = new FormData();
    form.append('file', file);
    return unwrap(
      await clientFetch<ApiEnvelope<AvatarUploadResult>>(`${BASE}/nurse_profiles/avatar`, {
        method: 'POST',
        body: form,
      }),
    );
  },
};
