/**
 * Stickers, badges, report cards (legacy CI printables_reports/*).
 */
import { apiUrl } from '../lib/apiOrigin'
import { ApiHttpError, apiFetch, getStoredToken } from './http'

export type ClassOption = { class_section_id?: number; id?: number; class_section_name?: string }

export type StudentOption = {
  id: number | string
  firstname?: string
  lastname?: string
  registration_grade?: string
  gender?: string
}

export async function fetchStickerFormOptions(params?: {
  school_year?: string
  semester?: string
}): Promise<{
  classes?: ClassOption[]
  students?: StudentOption[]
}> {
  const qs = new URLSearchParams()
  if (params?.school_year) qs.set('school_year', params.school_year)
  if (params?.semester) qs.set('semester', params.semester)
  const suffix = qs.toString() ? `?${qs}` : ''
  return apiFetch(`/api/v1/administrator/printables/stickers/form-options${suffix}`)
}

export async function fetchStudentsByClass(classId: number | string): Promise<StudentOption[]> {
  const body = await apiFetch<{ students?: StudentOption[] } | StudentOption[]>(
    `/api/v1/administrator/students/by-class/${encodeURIComponent(String(classId))}`,
  )
  if (Array.isArray(body)) return body
  return body.students ?? []
}

export async function postStickerGenerate(formData: FormData): Promise<Blob> {
  const headers = new Headers({ Accept: 'application/pdf,*/*' })
  const token = getStoredToken()
  if (token) headers.set('Authorization', `Bearer ${token}`)
  const res = await fetch(apiUrl('/api/v1/administrator/printables/stickers/generate'), {
    method: 'POST',
    headers,
    body: formData,
  })
  if (!res.ok) {
    const errBody: unknown = await res.json().catch(() => null)
    const msg =
      typeof errBody === 'object' && errBody !== null && 'message' in errBody
        ? String((errBody as { message?: unknown }).message ?? '')
        : ''
    throw new ApiHttpError(msg || `HTTP ${res.status}`, res.status, errBody)
  }
  const raw = await res.blob()
  return new Blob([await raw.arrayBuffer()], { type: 'application/pdf' })
}

export async function postBadgeGenerate(formData: FormData): Promise<Blob> {
  const headers = new Headers({ Accept: 'application/pdf,*/*' })
  const token = getStoredToken()
  if (token) headers.set('Authorization', `Bearer ${token}`)
  const res = await fetch(apiUrl('/api/v1/badges/pdf'), {
    method: 'POST',
    headers,
    body: formData,
  })
  if (!res.ok) {
    const errBody: unknown = await res.json().catch(() => null)
    const msg =
      typeof errBody === 'object' && errBody !== null && 'message' in errBody
        ? String((errBody as { message?: unknown }).message ?? '')
        : ''
    throw new ApiHttpError(msg || `HTTP ${res.status}`, res.status, errBody)
  }
  const raw = await res.blob()
  return new Blob([await raw.arrayBuffer()], { type: 'application/pdf' })
}

export type StickerPreviewCounts = {
  students?: Array<{ student_id: number | string; primary_count?: number }>
  totals?: { stickers?: number; students?: number }
}

export async function fetchStickerPreviewCounts(classId?: number | string | null): Promise<StickerPreviewCounts> {
  const qs = new URLSearchParams()
  if (classId) qs.set('class_id', String(classId))
  const suffix = qs.toString() ? `?${qs}` : ''
  const body = await apiFetch<
    StickerPreviewCounts & { status?: string; data?: StickerPreviewCounts }
  >(`/api/v1/administrator/printables/stickers/preview${suffix}`)
  if (body.data) return body.data
  return body
}

export type BadgeUserRow = Record<string, unknown>

export async function fetchBadgeFormOptions(params?: {
  school_year?: string
  semester?: string
}): Promise<{
  active_role?: string
  rolesTabs?: Record<string, string>
  schoolYears?: string[]
  selectedYear?: string
  selectedStudentIds?: number[]
  selectedUserIds?: number[]
  users?: BadgeUserRow[]
}> {
  const qs = new URLSearchParams()
  if (params?.school_year) qs.set('school_year', params.school_year)
  if (params?.semester) qs.set('semester', params.semester)
  const suffix = qs.toString() ? `?${qs}` : ''
  const body = await apiFetch<{
    ok?: boolean
    data?: {
      active_role?: string
      rolesTabs?: Record<string, string>
      schoolYears?: string[]
      selectedYear?: string
      selectedStudentIds?: number[]
      selectedUserIds?: number[]
      users?: BadgeUserRow[]
    }
  } & {
    active_role?: string
    rolesTabs?: Record<string, string>
    schoolYears?: string[]
    selectedYear?: string
    selectedStudentIds?: number[]
    selectedUserIds?: number[]
    users?: BadgeUserRow[]
  }>(`/api/v1/administrator/printables/badges/form-options${suffix}`)
  return body.data ?? body
}

export async function fetchBadgePrintStatus(params: {
  user_ids?: (number | string)[]
  student_ids?: (number | string)[]
  school_year?: string
}): Promise<{
  ok?: boolean
  data?: Record<string, { count?: number }>
  csrf_token?: string
  csrf_hash?: string
}> {
  const qs = new URLSearchParams()
  for (const id of params.user_ids ?? []) qs.append('user_ids[]', String(id))
  for (const id of params.student_ids ?? []) qs.append('student_ids[]', String(id))
  if (params.school_year) qs.set('school_year', params.school_year)
  return apiFetch(`/api/v1/badges/print-status?${qs}`)
}

export type ReportCardMeta = {
  ok?: boolean
  schoolYears?: string[]
  semesters?: string[]
  selectedYear?: string
  selectedSemester?: string
  students?: Array<{ id: number | string; firstname?: string; lastname?: string; class_section_name?: string }>
  classSections?: Array<{ class_section_id?: number; id?: number; class_section_name?: string }>
}

export async function fetchReportCardMeta(params?: {
  school_year?: string
  semester?: string
}): Promise<ReportCardMeta> {
  const qs = new URLSearchParams()
  if (params?.school_year) qs.set('school_year', params.school_year)
  if (params?.semester) qs.set('semester', params.semester)
  const suffix = qs.toString() ? `?${qs}` : ''
  return apiFetch(`/api/v1/administrator/printables/report-card/meta${suffix}`)
}

export async function fetchReportCardAck(params: {
  student_id: number | string
  school_year?: string
  semester?: string
}): Promise<{ ok?: boolean; viewed_at?: string; signed_at?: string; signed_name?: string }> {
  const qs = new URLSearchParams()
  qs.set('student_id', String(params.student_id))
  if (params.school_year) qs.set('school_year', params.school_year)
  if (params.semester) qs.set('semester', params.semester ?? '')
  return apiFetch(`/api/v1/administrator/printables/report-card/ack?${qs}`)
}

export async function fetchReportCardCompleteness(params: {
  class_section_id: number | string
  school_year?: string
  semester?: string
}): Promise<{
  ok?: boolean
  students?: Array<Record<string, unknown>>
  summary?: Record<string, unknown>
  used_fallback?: boolean
}> {
  const qs = new URLSearchParams()
  qs.set('class_section_id', String(params.class_section_id))
  if (params.school_year) qs.set('school_year', params.school_year ?? '')
  if (params.semester) qs.set('semester', params.semester ?? '')
  return apiFetch(`/api/v1/administrator/printables/report-card/completeness?${qs}`)
}

/** Build absolute API URL for iframe / window.open (report PDF HTML). */
export function reportCardStudentUrl(
  studentId: number | string,
  opts: { school_year: string; semester?: string; download?: boolean; report_date?: string },
): string {
  const qs = new URLSearchParams()
  qs.set('school_year', opts.school_year)
  if (opts.semester) qs.set('semester', opts.semester)
  if (opts.download) qs.set('download', '1')
  if (opts.report_date) qs.set('report_date', opts.report_date)
  qs.set('cb', String(Date.now()))
  return apiUrl(`/api/v1/reports/report-cards/students/${encodeURIComponent(String(studentId))}?${qs}`)
}

export function reportCardClassUrl(
  classSectionId: number | string,
  opts: { school_year: string; semester?: string; download?: boolean; report_date?: string },
): string {
  const qs = new URLSearchParams()
  qs.set('school_year', opts.school_year)
  if (opts.semester) qs.set('semester', opts.semester)
  if (opts.download) qs.set('download', '1')
  if (opts.report_date) qs.set('report_date', opts.report_date)
  qs.set('cb', String(Date.now()))
  return apiUrl(`/api/v1/reports/report-cards/classes/${encodeURIComponent(String(classSectionId))}?${qs}`)
}

/** HTML document for iframe preview (Bearer auth; unlike raw iframe src). */
export async function fetchReportCardStudentHtml(
  studentId: number | string,
  opts: { school_year: string; semester?: string; report_date?: string },
): Promise<string> {
  const qs = new URLSearchParams()
  qs.set('school_year', opts.school_year)
  if (opts.semester) qs.set('semester', opts.semester)
  if (opts.report_date) qs.set('report_date', opts.report_date)
  qs.set('cb', String(Date.now()))
  const headers = new Headers({ Accept: 'text/html' })
  const token = getStoredToken()
  if (token) headers.set('Authorization', `Bearer ${token}`)
  const path = `/api/v1/reports/report-cards/students/${encodeURIComponent(String(studentId))}?${qs}`
  const res = await fetch(apiUrl(path), { headers })
  if (!res.ok) throw new ApiHttpError(`HTTP ${res.status}`, res.status, null)
  return res.text()
}

export async function fetchReportCardClassHtml(
  classSectionId: number | string,
  opts: { school_year: string; semester?: string; report_date?: string },
): Promise<string> {
  const qs = new URLSearchParams()
  qs.set('school_year', opts.school_year)
  if (opts.semester) qs.set('semester', opts.semester)
  if (opts.report_date) qs.set('report_date', opts.report_date)
  qs.set('cb', String(Date.now()))
  const headers = new Headers({ Accept: 'text/html' })
  const token = getStoredToken()
  if (token) headers.set('Authorization', `Bearer ${token}`)
  const path = `/api/v1/reports/report-cards/classes/${encodeURIComponent(String(classSectionId))}?${qs}`
  const res = await fetch(apiUrl(path), { headers })
  if (!res.ok) throw new ApiHttpError(`HTTP ${res.status}`, res.status, null)
  return res.text()
}

/** Opens PDF download in new tab (authenticated GET). */
export async function openReportCardDownload(url: string): Promise<void> {
  const headers = new Headers({ Accept: 'application/pdf,*/*' })
  const token = getStoredToken()
  if (token) headers.set('Authorization', `Bearer ${token}`)
  const res = await fetch(url, { headers })
  if (!res.ok) throw new ApiHttpError(`HTTP ${res.status}`, res.status, null)
  const raw = await res.blob()
  const blob = new Blob([await raw.arrayBuffer()], { type: 'application/pdf' })
  window.open(URL.createObjectURL(blob), '_blank', 'noopener')
}
