import { api } from '@/core/services/api'
import type { PaginatedApiResponse } from '@/core/types/api'
import type {
  DocumentUploadType,
  ListMembershipApplicationsParams,
  MembershipApplicationApiResponse,
  MembershipApplicationFormState,
  MembershipApplicationListItem,
  MembershipApplicationReviewPayload,
  MembershipApplicationReviewResponse,
  MembershipApplicationSubmitResponse,
  BatchCompleteResponse,
  MembershipApplicationUpdateResponse,
  MemberLookupResponse,
  UpdateMembershipApplicationPayload,
} from '../types/membership-application.types'

function appendFormData(formData: FormData, key: string, value: string | number | File) {
  formData.append(key, String(value))
}

// Build form data for membership application
export function buildMembershipApplicationFormData(
  form: MembershipApplicationFormState,
): FormData {
  const formData = new FormData()

  Object.entries(form.applicant).forEach(([key, value]) => {
    if (value !== '') {
      appendFormData(formData, `applicant[${key}]`, value)
    }
  })

  form.heirs.forEach((heir, index) => {
    Object.entries(heir).forEach(([key, value]) => {
      if (value !== '') {
        appendFormData(formData, `heirs[${index}][${key}]`, value)
      }
    })
  })

  if (form.references.proposer.ic_number.trim()) {
    appendFormData(formData, 'references[proposer_ic_number]', form.references.proposer.ic_number.trim())
  }

  if (form.references.supporter.ic_number.trim()) {
    appendFormData(formData, 'references[supporter_ic_number]', form.references.supporter.ic_number.trim())
  }

  Object.entries(form.documents).forEach(([key, file]) => {
    if (file instanceof File) {
      formData.append(`documents[${key}]`, file)
    }
  })

  return formData
}

// Submit membership application
export async function submitMembershipApplication(
  form: MembershipApplicationFormState,
): Promise<MembershipApplicationSubmitResponse> {
  const formData = buildMembershipApplicationFormData(form)

  const { data } = await api.post<MembershipApplicationSubmitResponse>(
    '/v1/public/membership-applications',
    formData,
    {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    },
  )

  return data
}

// Lookup member by IC number
export async function lookupMemberByIcNumber(icNumber: string): Promise<MemberLookupResponse> {
  const { data } = await api.get<MemberLookupResponse>('/v1/public/membership-applications/member-lookup', {
    params: { ic_number: icNumber.trim() },
  })

  return data
}

// List membership applications
export async function listMembershipApplications(
  params: ListMembershipApplicationsParams,
): Promise<PaginatedApiResponse<MembershipApplicationListItem>> {
  const { data } = await api.get<PaginatedApiResponse<MembershipApplicationListItem>>(
    '/v1/membership-applications',
    { params },
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Failed to load membership applications')
  }

  return data
}

// Get membership application
export async function getMembershipApplication(id: string): Promise<MembershipApplicationApiResponse> {
  const { data } = await api.get<MembershipApplicationApiResponse>(`/v1/membership-applications/${id}`)

  if (!data.success) {
    throw new Error(data.message ?? 'Failed to load membership application')
  }

  return data
}

// Update membership application
export async function updateMembershipApplication(
  id: string,
  payload: UpdateMembershipApplicationPayload,
): Promise<MembershipApplicationUpdateResponse> {
  const { data } = await api.patch<MembershipApplicationUpdateResponse>(
    `/v1/membership-applications/${id}`,
    payload,
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Failed to update membership application')
  }

  return data
}

// Upload membership application document
export async function uploadMembershipApplicationDocument(
  id: string,
  type: DocumentUploadType,
  file: File,
): Promise<MembershipApplicationUpdateResponse> {
  const formData = new FormData()
  formData.append('type', type)
  formData.append('file', file)

  const { data } = await api.post<MembershipApplicationUpdateResponse>(
    `/v1/membership-applications/${id}/documents`,
    formData,
    {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    },
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Failed to upload document')
  }

  return data
}

// Submit management review
export async function submitManagementReview(
  id: string,
  payload: MembershipApplicationReviewPayload,
): Promise<MembershipApplicationReviewResponse> {
  const { data } = await api.post<MembershipApplicationReviewResponse>(
    `/v1/membership-applications/${id}/management-review`,
    payload,
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Failed to submit management review')
  }

  return data
}

// Submit board review
export async function submitBoardReview(
  id: string,
  payload: MembershipApplicationReviewPayload,
): Promise<MembershipApplicationReviewResponse> {
  const { data } = await api.post<MembershipApplicationReviewResponse>(
    `/v1/membership-applications/${id}/board-review`,
    payload,
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Failed to submit board review')
  }

  return data
}

// Complete membership application
export async function completeMembershipApplication(
  id: string,
): Promise<MembershipApplicationReviewResponse> {
  const { data } = await api.post<MembershipApplicationReviewResponse>(
    `/v1/membership-applications/${id}/complete`,
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Failed to complete membership application')
  }

  return data
}

export async function batchCompleteMembershipApplications(
  applicationIds: string[],
): Promise<BatchCompleteResponse> {
  const { data } = await api.post<BatchCompleteResponse>(
    '/v1/membership-applications/batch-complete',
    { application_ids: applicationIds },
  )

  return data
}

// Fetch membership application document/ view in modal
export async function fetchMembershipApplicationDocument(
  applicationId: string,
  documentId: string,
  mimeType?: string | null,
): Promise<Blob> {
  const response = await api.get(
    `/v1/membership-applications/${applicationId}/documents/${documentId}/download`,
    { responseType: 'blob' },
  )

  const contentType =
    mimeType ||
    (typeof response.headers['content-type'] === 'string' ? response.headers['content-type'] : null) ||
    'application/octet-stream'

  return new Blob([response.data], { type: contentType })
}

// Download membership application document
export async function downloadMembershipApplicationDocument(
  applicationId: string,
  documentId: string,
  fileName: string,
  mimeType?: string | null,
): Promise<void> {
  const blob = await fetchMembershipApplicationDocument(applicationId, documentId, mimeType)
  const url = window.URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = fileName
  link.click()
  window.URL.revokeObjectURL(url)
}
