import { api } from '@/core/services/api'
import type { PaginatedApiResponse } from '@/core/types/api'
import type {
  ActivityDetail,
  ActivityListItem,
  ActivityReport,
  ActivityType,
  CreateActivityReportPayload,
  CreateActivityPayload,
  CreateActivityTypePayload,
  ListActivitiesParams,
  UpdateActivityFiles,
  UpdateActivityPayload,
  UpdateActivityReportPayload,
} from '../types/activity.types'

type ActivityApiResponse = {
  success: boolean
  data: ActivityDetail
  message?: string
}

type ActivityReportApiResponse = {
  success: boolean
  data: ActivityReport
  message?: string
}

function appendIfPresent(formData: FormData, key: string, value: string | null | undefined) {
  if (value !== null && value !== undefined && value !== '') {
    formData.append(key, value)
  }
}

export function buildActivityFormData(
  payload: UpdateActivityPayload,
  files: UpdateActivityFiles = {},
  options: { method?: 'PUT' } = {},
): FormData {
  const formData = new FormData()

  formData.append('activity_type_id', payload.activity_type_id)
  formData.append('title', payload.title)
  formData.append('is_active', payload.is_active ? '1' : '0')
  appendIfPresent(formData, 'reference_number', payload.reference_number ?? undefined)
  appendIfPresent(formData, 'description', payload.description ?? undefined)
  appendIfPresent(formData, 'start_datetime', payload.start_datetime ?? undefined)
  appendIfPresent(formData, 'end_datetime', payload.end_datetime ?? undefined)
  appendIfPresent(formData, 'organizer', payload.organizer ?? undefined)
  appendIfPresent(formData, 'location', payload.location ?? undefined)

  files.documents?.forEach((file, index) => {
    formData.append(`documents[${index}]`, file)
  })

  files.gallery?.forEach((file, index) => {
    formData.append(`gallery[${index}]`, file)
  })

  if (options.method === 'PUT') {
    formData.append('_method', 'PUT')
  }

  return formData
}

export async function listActivities(
  params: ListActivitiesParams,
): Promise<PaginatedApiResponse<ActivityListItem>> {
  const { data } = await api.get<PaginatedApiResponse<ActivityListItem>>('/v1/activities', {
    params,
  })

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memuatkan senarai aktiviti.')
  }

  return data
}

export async function listActivityTypes(): Promise<ActivityType[]> {
  const { data } = await api.get<PaginatedApiResponse<ActivityType>>('/v1/activity-types', {
    params: { per_page: 1000 },
  })

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memuatkan jenis aktiviti.')
  }

  return data.data
}

type ActivityTypeApiResponse = {
  success: boolean
  data: ActivityType
  message?: string
}

export async function createActivityType(
  payload: CreateActivityTypePayload,
): Promise<ActivityType> {
  const { data } = await api.post<ActivityTypeApiResponse>('/v1/activity-types', payload)

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal menambah jenis aktiviti.')
  }

  return data.data
}

export async function getActivity(id: string): Promise<ActivityDetail> {
  const { data } = await api.get<ActivityApiResponse>(`/v1/activities/${id}`)

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memuatkan butiran aktiviti.')
  }

  return data.data
}

export async function updateActivity(
  id: string,
  payload: UpdateActivityPayload,
  files: UpdateActivityFiles = {},
): Promise<ActivityDetail> {
  const formData = buildActivityFormData(payload, files, { method: 'PUT' })

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

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal mengemaskini aktiviti.')
  }

  return data.data
}

export async function createActivity(
  payload: CreateActivityPayload,
  files: UpdateActivityFiles = {},
): Promise<ActivityDetail> {
  const formData = buildActivityFormData(payload, files)

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

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal mendaftar aktiviti.')
  }

  return data.data
}

export async function uploadActivityGalleryImage(
  activityId: string,
  file: File,
): Promise<ActivityDetail> {
  const formData = new FormData()
  formData.append('file', file)

  const { data } = await api.post<ActivityApiResponse>(
    `/v1/activities/${activityId}/gallery`,
    formData,
    {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    },
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memuat naik imej galeri.')
  }

  return data.data
}

export async function uploadActivityDocument(
  activityId: string,
  file: File,
): Promise<ActivityDetail> {
  const formData = new FormData()
  formData.append('file', file)

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

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memuat naik dokumen.')
  }

  return data.data
}

export async function deleteActivityGalleryImage(
  activityId: string,
  imageId: string,
): Promise<ActivityDetail> {
  const { data } = await api.delete<ActivityApiResponse>(
    `/v1/activities/${activityId}/gallery/${imageId}`,
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memadam imej galeri.')
  }

  return data.data
}

export async function deleteActivityDocument(
  activityId: string,
  documentId: string,
): Promise<ActivityDetail> {
  const { data } = await api.delete<ActivityApiResponse>(
    `/v1/activities/${activityId}/documents/${documentId}`,
  )

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memadam dokumen.')
  }

  return data.data
}

export async function fetchActivityGalleryImage(
  activityId: string,
  imageId: string,
  mimeType?: string | null,
): Promise<Blob> {
  const response = await api.get(`/v1/activities/${activityId}/gallery/${imageId}`, {
    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 })
}

export async function fetchActivityDocument(
  activityId: string,
  documentId: string,
  mimeType?: string | null,
): Promise<Blob> {
  const response = await api.get(
    `/v1/activities/${activityId}/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 })
}

export async function downloadActivityDocument(
  activityId: string,
  documentId: string,
  fileName: string,
  mimeType?: string | null,
): Promise<void> {
  const blob = await fetchActivityDocument(activityId, 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)
}

export async function createActivityReport(
  payload: CreateActivityReportPayload,
): Promise<ActivityReport> {
  const { data } = await api.post<ActivityReportApiResponse>('/v1/activity-reports', payload)

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal menambah laporan aktiviti.')
  }

  return data.data
}

export async function updateActivityReport(
  id: string,
  payload: UpdateActivityReportPayload,
): Promise<ActivityReport> {
  const { data } = await api.put<ActivityReportApiResponse>(`/v1/activity-reports/${id}`, payload)

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal mengemaskini laporan aktiviti.')
  }

  return data.data
}

type ActivityDeleteResponse = {
  success: boolean
  message?: string
}

export async function deleteActivity(id: string): Promise<void> {
  const { data } = await api.delete<ActivityDeleteResponse>(`/v1/activities/${id}`)

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memadam aktiviti.')
  }
}

type ActivityReportDeleteResponse = {
  success: boolean
  message?: string
}

export async function deleteActivityReport(id: string): Promise<void> {
  const { data } = await api.delete<ActivityReportDeleteResponse>(`/v1/activity-reports/${id}`)

  if (!data.success) {
    throw new Error(data.message ?? 'Gagal memadam laporan aktiviti.')
  }
}
