/**
 * Administrator grading API (parity with CI `Views/grading/*.php`).
 * Base: `/api/v1/grading/...` with JWT.
 */
import { apiFetch } from './http'

const BASE = '/api/v1/grading'

export type GradingScoreRow = {
  id?: number
  score?: number | string | null
  comment?: string | null
}

export type GradingSectionScoreStudent = {
  student_id: number
  firstname?: string | null
  lastname?: string | null
  school_id?: string | null
  score?: number | string | null
  scores?: Record<string, number | string | null>
  comments?: Record<
    string,
    {
      comment?: string | null
      comment_review?: string | null
      commented_by?: string | number | null
      reviewed_by?: string | number | null
    }
  >
}

export type GradingScoreFormPayload = {
  scoresLocked?: boolean
  student?: { id?: number; firstname?: string; lastname?: string; school_id?: string | null }
  classSectionId?: number
  class_section_name?: string | null
  scores?: GradingScoreRow[]
}

export type GradingSectionScorePayload = {
  ok?: boolean
  students?: GradingSectionScoreStudent[]
  headers?: number[]
  semester?: string
  school_year?: string
  class_section_id?: number | string
  class_section_name?: string | null
  scores_locked?: boolean
  missing_ok_map?: Record<string, unknown>
}

export type AllDecisionRow = {
  student_id: number
  school_id?: string | null
  firstname?: string | null
  lastname?: string | null
  gender?: string | null
  class_section_id?: number | string | null
  class_section_name?: string | null
  fall_score?: number | string | null
  spring_score?: number | string | null
  year_score?: number | string | null
  decision?: string | null
  source?: string | null
  notes?: string | null
  saved?: boolean
  is_trophy?: boolean
}

export type AllDecisionsPayload = {
  ok?: boolean
  rows?: AllDecisionRow[]
  generated?: boolean
  school_year?: string
}

function q(sp: URLSearchParams): string {
  const s = sp.toString()
  return s ? `?${s}` : ''
}

export async function fetchGradingMain(searchParams: URLSearchParams): Promise<unknown> {
  return apiFetch(`${BASE}/overview${q(searchParams)}`)
}

export async function fetchGradingScoreForm(
  scoreType: string,
  classSectionId: string,
  studentId: string,
  searchParams: URLSearchParams,
): Promise<GradingScoreFormPayload> {
  return apiFetch(`${BASE}/scores/${encodeURIComponent(scoreType)}/${encodeURIComponent(classSectionId)}/${encodeURIComponent(studentId)}${q(searchParams)}`)
}

function scoreCollectionPath(scoreType: string): string {
  switch (scoreType) {
    case 'homework':
      return '/api/v1/scores/homework'
    case 'quiz':
      return '/api/v1/scores/quizzes'
    case 'project':
      return '/api/v1/scores/projects'
    case 'midterm':
      return '/api/v1/scores/midterm'
    case 'final':
      return '/api/v1/scores/final'
    case 'comments':
      return '/api/v1/scores/comments'
    default:
      throw new Error(`Unsupported score type: ${scoreType}`)
  }
}

export async function fetchGradingSectionScoreTable(
  scoreType: string,
  classSectionId: string,
  searchParams: URLSearchParams,
): Promise<GradingSectionScorePayload> {
  const next = new URLSearchParams(searchParams)
  next.set('class_section_id', classSectionId)
  return apiFetch(`${scoreCollectionPath(scoreType)}${q(next)}`)
}

export async function postGradingScoreUpdate(
  body: Record<string, unknown>,
): Promise<unknown> {
  return apiFetch(`${BASE}/scores`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function postGradingSectionScoreUpdate(
  scoreType: string,
  body: Record<string, unknown>,
): Promise<unknown> {
  const method = scoreType === 'comments' ? 'PUT' : 'POST'
  return apiFetch(scoreCollectionPath(scoreType), {
    method,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchBelowSixty(searchParams: URLSearchParams): Promise<unknown> {
  return apiFetch(`${BASE}/below-sixty${q(searchParams)}`)
}

export async function fetchAllDecisions(
  searchParams: URLSearchParams,
): Promise<AllDecisionsPayload> {
  return apiFetch(`${BASE}/decisions${q(searchParams)}`)
}

export async function postGenerateAllDecisions(body: Record<string, unknown>): Promise<{
  ok?: boolean
  saved_count?: number
}> {
  return apiFetch(`${BASE}/decisions/generate`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchBelowSixtyDecisions(
  searchParams: URLSearchParams,
): Promise<unknown> {
  return apiFetch(`${BASE}/below-sixty/decisions${q(searchParams)}`)
}

export async function postBelowSixtyDecision(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch(`${BASE}/below-sixty/decisions`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchBelowSixtyDecisionDetails(
  searchParams: URLSearchParams,
): Promise<unknown> {
  return apiFetch(`${BASE}/below-sixty/decisions/details${q(searchParams)}`)
}

export async function fetchBelowSixtyDecisionEmailEditor(
  searchParams: URLSearchParams,
): Promise<{
  student_id?: number
  student_name?: string
  school_year?: string
  semester?: string
  decision?: string
  subject?: string
  html?: string
  year_score?: number | string | null
}> {
  return apiFetch(`${BASE}/below-sixty/decisions/email${q(searchParams)}`)
}

export async function postBelowSixtyDecisionEmail(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch(`${BASE}/below-sixty/decisions/email`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchBelowSixtyEmailEditor(searchParams: URLSearchParams): Promise<{
  studentId?: number
  studentName?: string
  semester?: string
  schoolYear?: string
  subject?: string
  html?: string
}> {
  return apiFetch(`${BASE}/below-sixty/email-editor${q(searchParams)}`)
}

export async function postBelowSixtyEmail(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch(`${BASE}/below-sixty/email`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function postBelowSixtyStatus(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch(`${BASE}/below-sixty/status`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchHomeworkTracking(
  searchParams: URLSearchParams,
): Promise<unknown> {
  return apiFetch(`${BASE}/homework-tracking${q(searchParams)}`)
}

export async function fetchParticipation(searchParams: URLSearchParams): Promise<unknown> {
  return apiFetch(`/api/v1/scores/participation${q(searchParams)}`)
}

export async function postParticipation(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch('/api/v1/scores/participation', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchPlacementIndex(searchParams: URLSearchParams): Promise<unknown> {
  return apiFetch(`${BASE}/placement-index${q(searchParams)}`)
}

export async function postPlacementAll(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch(`${BASE}/placement-all`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchPlacementSection(searchParams: URLSearchParams): Promise<unknown> {
  return apiFetch(`${BASE}/placement${q(searchParams)}`)
}

export async function postPlacementSection(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch(`${BASE}/placement`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchPlacementBatch(batchId: string | number): Promise<unknown> {
  return apiFetch(`${BASE}/placement-batch/${batchId}`)
}

export async function postPlacementBatch(
  batchId: string | number,
  body: Record<string, unknown>,
): Promise<unknown> {
  return apiFetch(`${BASE}/placement-batch/${batchId}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}

export async function fetchScheduleMeetingForm(
  searchParams: URLSearchParams,
): Promise<unknown> {
  return apiFetch(`${BASE}/schedule-meeting${q(searchParams)}`)
}

export async function postScheduleMeeting(body: Record<string, unknown>): Promise<unknown> {
  return apiFetch(`${BASE}/schedule-meeting`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
}
