import { apiFetch } from './http'

export type SchoolYearStatus = 'draft' | 'active' | 'closed' | 'archived' | string

export type SchoolYearRecord = {
  id: number
  name: string
  start_date: string
  end_date: string
  status: SchoolYearStatus
  is_current: boolean
  closed_at?: string | null
  closed_by?: number | null
}

export type SchoolYearSummary = {
  school_year: SchoolYearRecord
  totals: {
    students_considered: number
    students_blocked: number
    parents_with_balances: number
    net_balance_to_transfer: number
  }
}

export type SchoolYearPromotionRow = {
  student_id: number
  student_name: string
  parent_id?: number | null
  current_grade?: string | null
  current_class?: string | null
  promotion_action: string
  target_grade?: string | null
  target_class?: string | null
  target_class_section_id?: number | null
  warnings?: string[]
  decision?: string | null
  score?: number | null
}

export type SchoolYearPromotionPreview = {
  rows: SchoolYearPromotionRow[]
  summary: {
    total_students: number
    promote: number
    repeat: number
    graduate: number
    transfer: number
    withdraw: number
    hold: number
  }
}

export type SchoolYearParentBalanceRow = {
  parent_id: number
  parent_name?: string | null
  student_names?: string[]
  old_unpaid_balance: number
  credit_balance: number
  amount_to_transfer: number
  existing_transfer_conflict?: boolean
}

export type SchoolYearParentBalancePreview = {
  rows: SchoolYearParentBalanceRow[]
  summary: {
    parents_with_non_zero_balance: number
    parents_with_credit_balance: number
    total_old_unpaid_balance: number
    total_credit_balance: number
    net_balance_to_transfer: number
    existing_transfer_conflicts: number
  }
}

export type SchoolYearCloseValidation = {
  can_close: boolean
  errors: string[]
  warnings: string[]
  promotion_summary: SchoolYearPromotionPreview['summary']
  financial_summary: SchoolYearParentBalancePreview['summary']
}

export type SchoolYearClosePreview = {
  school_year: SchoolYearRecord
  validation: SchoolYearCloseValidation
  promotion_preview: SchoolYearPromotionPreview
  parent_balances: SchoolYearParentBalancePreview
}

export type SchoolYearCloseResult = {
  closed_school_year: SchoolYearRecord
  new_school_year: SchoolYearRecord
  promotion_counts?: Record<string, number>
  balance_counts?: Record<string, number>
}

export type SaveSchoolYearPayload = {
  name: string
  start_date: string
  end_date: string
}

export type CloseSchoolYearPayload = {
  new_school_year: SaveSchoolYearPayload
  transfer_unpaid_balances?: boolean
  confirmation?: string
}

type ApiListResponse = {
  ok?: boolean
  data?: SchoolYearRecord[]
}

type ApiRecordResponse = {
  ok?: boolean
  data?: SchoolYearRecord
}

type ApiSummaryResponse = {
  ok?: boolean
  data?: SchoolYearSummary
}

type ApiValidationResponse = {
  ok?: boolean
  validation?: SchoolYearCloseValidation
}

type ApiPreviewResponse = {
  ok?: boolean
  data?: SchoolYearClosePreview
}

type ApiParentBalancesResponse = {
  ok?: boolean
  data?: SchoolYearParentBalancePreview
}

type ApiPromotionPreviewResponse = {
  ok?: boolean
  data?: SchoolYearPromotionPreview
}

type ApiCloseResponse = {
  ok?: boolean
  data?: SchoolYearCloseResult
}

export async function fetchSchoolYears(): Promise<SchoolYearRecord[]> {
  const response = await apiFetch<ApiListResponse>('/api/v1/school-years')
  return response.data ?? []
}

export async function createSchoolYear(payload: SaveSchoolYearPayload): Promise<SchoolYearRecord> {
  const response = await apiFetch<ApiRecordResponse>('/api/v1/school-years', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  })

  if (!response.data) {
    throw new Error('School year creation returned no record.')
  }

  return response.data
}

export async function updateSchoolYear(
  schoolYearId: number,
  payload: SaveSchoolYearPayload,
): Promise<SchoolYearRecord> {
  const response = await apiFetch<ApiRecordResponse>(`/api/v1/school-years/${schoolYearId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  })

  if (!response.data) {
    throw new Error('School year update returned no record.')
  }

  return response.data
}

export async function fetchSchoolYearSummary(schoolYearId: number): Promise<SchoolYearSummary> {
  const response = await apiFetch<ApiSummaryResponse>(`/api/v1/school-years/${schoolYearId}/summary`)
  if (!response.data) {
    throw new Error('School year summary returned no data.')
  }
  return response.data
}

export async function validateSchoolYearClose(
  schoolYearId: number,
  payload: CloseSchoolYearPayload,
): Promise<SchoolYearCloseValidation> {
  const response = await apiFetch<ApiValidationResponse>(
    `/api/v1/school-years/${schoolYearId}/validate-close`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    },
  )

  if (!response.validation) {
    throw new Error('School year validation returned no payload.')
  }

  return response.validation
}

export async function previewSchoolYearClose(
  schoolYearId: number,
  payload: CloseSchoolYearPayload,
): Promise<SchoolYearClosePreview> {
  const response = await apiFetch<ApiPreviewResponse>(
    `/api/v1/school-years/${schoolYearId}/preview-close`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    },
  )

  if (!response.data) {
    throw new Error('School year close preview returned no payload.')
  }

  return response.data
}

export async function closeSchoolYear(
  schoolYearId: number,
  payload: CloseSchoolYearPayload,
): Promise<SchoolYearCloseResult> {
  const response = await apiFetch<ApiCloseResponse>(`/api/v1/school-years/${schoolYearId}/close`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  })

  if (!response.data) {
    throw new Error('School year close returned no payload.')
  }

  return response.data
}

export async function reopenSchoolYear(schoolYearId: number): Promise<SchoolYearRecord> {
  const response = await apiFetch<ApiRecordResponse>(`/api/v1/school-years/${schoolYearId}/reopen`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
  })

  if (!response.data) {
    throw new Error('School year reopen returned no payload.')
  }

  return response.data
}

export async function fetchSchoolYearParentBalances(
  schoolYearId: number,
  toSchoolYear?: string,
): Promise<SchoolYearParentBalancePreview> {
  const query = toSchoolYear ? `?to_school_year=${encodeURIComponent(toSchoolYear)}` : ''
  const response = await apiFetch<ApiParentBalancesResponse>(
    `/api/v1/school-years/${schoolYearId}/parent-balances${query}`,
  )

  if (!response.data) {
    throw new Error('Parent balances preview returned no payload.')
  }

  return response.data
}

export async function fetchSchoolYearPromotionPreview(
  schoolYearId: number,
  toSchoolYear?: string,
): Promise<SchoolYearPromotionPreview> {
  const query = toSchoolYear ? `?to_school_year=${encodeURIComponent(toSchoolYear)}` : ''
  const response = await apiFetch<ApiPromotionPreviewResponse>(
    `/api/v1/school-years/${schoolYearId}/promotion-preview${query}`,
  )

  if (!response.data) {
    throw new Error('Promotion preview returned no payload.')
  }

  return response.data
}
