import api from './client'

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface CadObjects {
  cad_file_id: string
  original_name: string
  processing_status: 'pending' | 'processing' | 'completed' | 'failed'
  parsed_objects: Record<string, unknown> | null
}

export interface RegenerateThumbnailResponse {
  cad_file_id: string
  original_name: string
  status: 'queued'
  task_id: string | null
}

// ---------------------------------------------------------------------------
// API functions
// ---------------------------------------------------------------------------

/**
 * Returns the URL to the thumbnail PNG for a CAD file.
 * Use directly in <img src={getCadThumbnailUrl(id)} /> – the browser will
 * handle the authenticated request via the axios interceptor when called
 * programmatically, or you can construct the URL for use in img tags when
 * the auth token is set as a header.
 *
 * For use in <img> tags without auth headers, prefer fetching as a blob and
 * creating an object URL (see fetchThumbnailBlob below).
 */
export function getCadThumbnailUrl(cadFileId: string): string {
  return `/api/cad/${cadFileId}/thumbnail`
}

/**
 * Fetch the thumbnail PNG as a Blob and return an object URL suitable for
 * use in <img src=...> without needing explicit auth headers.
 * Remember to call URL.revokeObjectURL() when the component unmounts.
 */
export async function fetchThumbnailBlob(cadFileId: string): Promise<string> {
  const res = await api.get<Blob>(`/cad/${cadFileId}/thumbnail`, {
    responseType: 'blob',
  })
  return URL.createObjectURL(res.data)
}

/**
 * Fetch the glTF model file as a Blob and return an object URL.
 * Remember to call URL.revokeObjectURL() when the consumer is done.
 */
export async function fetchModelBlob(cadFileId: string): Promise<string> {
  const res = await api.get<Blob>(`/cad/${cadFileId}/model`, {
    responseType: 'blob',
  })
  return URL.createObjectURL(res.data)
}

/**
 * Return the parsed_objects JSON for a CAD file.
 */
export async function getCadObjects(cadFileId: string): Promise<CadObjects> {
  const res = await api.get<CadObjects>(`/cad/${cadFileId}/objects`)
  return res.data
}

/**
 * Ask the backend to re-queue STEP processing for a CAD file (admin only).
 * Returns the Celery task_id (or null if the worker is not available).
 */
export async function regenerateThumbnail(
  cadFileId: string,
): Promise<RegenerateThumbnailResponse> {
  const res = await api.post<RegenerateThumbnailResponse>(
    `/cad/${cadFileId}/regenerate-thumbnail`,
  )
  return res.data
}

export interface GenerateGltfResponse {
  status: 'queued'
  task_id: string
  cad_file_id: string
}

/** Queue geometry GLB export directly from STEP via OCC (no Blender, no STL). */
export async function generateGltfGeometry(cadFileId: string): Promise<GenerateGltfResponse> {
  const res = await api.post<GenerateGltfResponse>(`/cad/${cadFileId}/generate-gltf-geometry`)
  return res.data
}

export interface ParsedObjectsResponse {
  cad_file_id: string
  original_name: string
  processing_status: string
  parsed_objects: {
    dimensions_mm?: { x: number; y: number; z: number }
    bbox_center_mm?: { x: number; y: number; z: number }
    [key: string]: unknown
  } | null
}

/** Return the parsed_objects metadata (dimensions, bbox) for a CAD file. */
export async function getParsedObjects(cadFileId: string): Promise<ParsedObjectsResponse> {
  const res = await api.get<ParsedObjectsResponse>(`/cad/${cadFileId}/parsed-objects`)
  return res.data
}

/** Force-reset a CAD file stuck in 'processing' to 'failed'. */
export async function resetStuckProcessing(cadFileId: string): Promise<{ status: string; message: string }> {
  const res = await api.post<{ status: string; message: string }>(`/cad/${cadFileId}/reset-stuck`)
  return res.data
}

// ---------------------------------------------------------------------------
// Part-material assignment
// ---------------------------------------------------------------------------

export interface PartMaterialEntry {
  type: 'library' | 'hex'
  value: string
}

export type PartMaterialMap = Record<string, PartMaterialEntry>

interface PartMaterialsResponse {
  cad_file_id: string
  part_materials: PartMaterialMap | null
}

/** Return the saved part-material assignments for a CAD file (empty object if none). */
export async function getPartMaterials(cadFileId: string): Promise<PartMaterialMap> {
  const res = await api.get<PartMaterialsResponse>(`/cad/${cadFileId}/part-materials`)
  return res.data.part_materials ?? {}
}

/** Replace the part-material assignment map for a CAD file. Returns the updated map. */
export async function savePartMaterials(
  cadFileId: string,
  map: PartMaterialMap,
): Promise<PartMaterialMap> {
  const res = await api.put<PartMaterialsResponse>(`/cad/${cadFileId}/part-materials`, map)
  return res.data.part_materials ?? {}
}

// ---------------------------------------------------------------------------
// Manual material overrides (partKey-keyed, Priority 4)
// ---------------------------------------------------------------------------

export interface ManualMaterialOverridesResponse {
  cad_file_id: string
  manual_material_overrides: Record<string, string> | null
}

/** Return the manual material overrides for a CAD file ({partKey: materialName}, empty if none). */
export async function getManualOverrides(cadFileId: string): Promise<Record<string, string>> {
  const res = await api.get<ManualMaterialOverridesResponse>(
    `/cad/${cadFileId}/manual-material-overrides`,
  )
  return res.data.manual_material_overrides ?? {}
}

/** Save manual material overrides keyed by partKey. Returns the saved map. */
export async function saveManualOverrides(
  cadFileId: string,
  overrides: Record<string, string>,
): Promise<Record<string, string>> {
  const res = await api.put<ManualMaterialOverridesResponse>(
    `/cad/${cadFileId}/manual-material-overrides`,
    { overrides },
  )
  return res.data.manual_material_overrides ?? {}
}
