import { APIClient, APIResponse, type AuthStoreType } from './base'

export const BASE_URL = import.meta.env.VITE_API_URL + '/classroom-compliance'

export const EMOJI_CLASSROOM_READY = '🍎'
export const EMOJI_NOT_CLASSROOM_READY = '🐛'
export const EMOJI_PRESENT = '✅'
export const EMOJI_ABSENT = '❌'
export const EMOJI_BEHAVIOR_GOOD = '😇'
export const EMOJI_BEHAVIOR_MEDIOCRE = '😐'
export const EMOJI_BEHAVIOR_POOR = '😡'

export enum ComplianceLevel {
  Good,
  Mediocre,
  Poor,
}

export const DEFAULT_CHECKLIST_ITEMS: Record<string, string[]> = {
  'Classroom Readiness': [
    'Tardy',
    'Out of Uniform',
    'Use of wireless tech',
    '10+ minute bathroom pass',
    'Not having laptop',
    'Not in assigned seat',
  ],
  Behavior: [
    'Talking out of turn',
    'Throwing objects in class',
    'Rude language / comments to peers',
    'Disrespectful towards the teacher',
    'Disrupting / distracting peers or teacher',
  ],
}

export interface Class {
  id: number
  number: number
  schoolYear: string
  scoreExpression: string
  scorePeriod: string
  archived: boolean
}

export interface ClassesResponseClass {
  id: number
  number: number
  schoolYear: string
  studentCount: number
  entryCount: number
  lastEntryDate: string
  archived: boolean
}

export interface Student {
  id: number
  name: string
  classId: number
  deskNumber: number
  removed: boolean
}

export interface Entry {
  date: string
  createdAt: number
  absent: boolean
  comment: string
  checklistItems: EntryChecklistItem[]
}

export interface EntryChecklistItem {
  item: string
  checked: boolean
  category: string
}

export function getDefaultEntry(dateStr: string): Entry {
  const defaultChecklistItems: EntryChecklistItem[] = []
  for (const category in DEFAULT_CHECKLIST_ITEMS) {
    for (const item of DEFAULT_CHECKLIST_ITEMS[category]) {
      defaultChecklistItems.push({ item, category, checked: false })
    }
  }
  defaultChecklistItems.sort((a, b) => {
    const cmpCat = a.category.localeCompare(b.category)
    if (cmpCat !== 0) return cmpCat
    return a.item.localeCompare(b.category)
  })
  return {
    date: dateStr,
    createdAt: Date.now(),
    absent: false,
    comment: '',
    checklistItems: defaultChecklistItems,
  }
}

export function getCategoryScore(entry: Entry, category: string): number | null {
  const matchingItems = entry.checklistItems.filter((ck) => ck.category === category)
  if (matchingItems.length === 0) return null
  const unchecked = matchingItems.filter((ck) => !ck.checked).length
  return unchecked / matchingItems.length
}

export function getComplianceLevel(entry: Entry, category: string): ComplianceLevel | null {
  const score = getCategoryScore(entry, category)
  if (score === null) return null
  if (score < 0.5) return ComplianceLevel.Poor
  if (score < 1) return ComplianceLevel.Mediocre
  return ComplianceLevel.Good
}

export interface EntriesResponseStudent {
  id: number
  classId: number
  name: string
  deskNumber: number
  removed: boolean
  entries: Record<string, Entry | null>
  score: number | null
}

export interface EntriesResponse {
  students: EntriesResponseStudent[]
  dates: string[]
}

export interface StudentDataPayload {
  name: string
  deskNumber: number
  removed: boolean
}

export interface EntriesPayloadStudent {
  id: number
  entries: Record<string, Entry | null>
}

export interface EntriesPayload {
  students: EntriesPayloadStudent[]
}

export interface StudentScore {
  id: number
  score: number | null
}

export interface ScoresResponse {
  scores: StudentScore[]
}

export interface StudentStatisticsOverview {
  attendanceRate: number
  entryCount: number
}

export interface ClassNote {
  id: number
  classId: number
  createdAt: number
  content: string
}

export class ClassroomComplianceAPIClient extends APIClient {
  constructor(authStore: AuthStoreType) {
    super(BASE_URL, authStore)
  }

  createClass(number: number, schoolYear: string): APIResponse<Class> {
    return super.post('/classes', { number: number, schoolYear: schoolYear })
  }

  getClasses(): APIResponse<ClassesResponseClass[]> {
    return super.get('/classes')
  }

  getClass(classId: number): APIResponse<Class> {
    return super.get(`/classes/${classId}`)
  }

  deleteClass(classId: number): APIResponse<void> {
    return super.delete(`/classes/${classId}`)
  }

  getClassNotes(classId: number): APIResponse<ClassNote[]> {
    return super.get(`/classes/${classId}/notes`)
  }

  createClassNote(classId: number, content: string): APIResponse<ClassNote> {
    return super.post(`/classes/${classId}/notes`, { content: content })
  }

  deleteClassNote(classId: number, noteId: number): APIResponse<void> {
    return super.delete(`/classes/${classId}/notes/${noteId}`)
  }

  resetStudentDesks(classId: number): APIResponse<void> {
    const url = `/classes/${classId}/reset-desk-numbers`
    const promise = fetch(this.baseUrl + url, {
      headers: this.getAuthHeaders(),
      method: 'PUT',
    })
    return new APIResponse(this.handleAPIResponseWithNoBody(promise))
  }

  toggleArchived(classId: number): APIResponse<void> {
    return super.postWithNoExpectedResponse(`/classes/${classId}/archived`, {})
  }

  updateScoreParameters(
    classId: number,
    scoreExpression: string,
    scorePeriod: string,
  ): APIResponse<Class> {
    return super.put(`/classes/${classId}/score-parameters`, {
      scoreExpression: scoreExpression,
      scorePeriod: scorePeriod,
    })
  }

  getStudents(classId: number): APIResponse<Student[]> {
    return super.get(`/classes/${classId}/students`)
  }

  getStudent(classId: number, studentId: number): APIResponse<Student> {
    return super.get(`/classes/${classId}/students/${studentId}`)
  }

  createStudent(classId: number, data: StudentDataPayload): APIResponse<Student> {
    return super.post(`/classes/${classId}/students`, data)
  }

  updateStudent(
    classId: number,
    studentId: number,
    data: StudentDataPayload,
  ): APIResponse<Student> {
    return super.put(`/classes/${classId}/students/${studentId}`, data)
  }

  moveStudentToOtherClass(
    classId: number,
    studentId: number,
    newClassId: number,
  ): APIResponse<void> {
    const url = `/classes/${classId}/students/${studentId}/class`
    const promise = fetch(this.baseUrl + url, {
      headers: this.getAuthHeaders(),
      method: 'PUT',
      body: JSON.stringify({ classId: newClassId }),
    })
    return new APIResponse(this.handleAPIResponseWithNoBody(promise))
  }

  deleteStudent(classId: number, studentId: number): APIResponse<void> {
    return super.delete(`/classes/${classId}/students/${studentId}`)
  }

  getEntries(classId: number, fromDate?: Date, toDate?: Date): APIResponse<EntriesResponse> {
    const params = new URLSearchParams()
    if (fromDate) {
      params.append('from', fromDate.toISOString().substring(0, 10))
    }
    if (toDate) {
      params.append('to', toDate.toISOString().substring(0, 10))
    }
    return super.get(`/classes/${classId}/entries?${params.toString()}`)
  }

  saveEntries(classId: number, payload: EntriesPayload): APIResponse<void> {
    return super.postWithNoExpectedResponse(`/classes/${classId}/entries`, payload)
  }

  getScores(classId: number, fromDate: Date, toDate: Date): APIResponse<ScoresResponse> {
    const params = new URLSearchParams()
    params.append('from', fromDate.toISOString().substring(0, 10))
    params.append('to', toDate.toISOString().substring(0, 10))
    return super.get(`/classes/${classId}/scores?${params.toString()}`)
  }

  getStudentEntries(classId: number, studentId: number): APIResponse<Entry[]> {
    return super.get(`/classes/${classId}/students/${studentId}/entries`)
  }

  getStudentStatisticsOverview(
    classId: number,
    studentId: number,
  ): APIResponse<StudentStatisticsOverview> {
    return super.get(`/classes/${classId}/students/${studentId}/overview`)
  }

  getStudentLabels(classId: number, studentId: number): APIResponse<string[]> {
    return super.get(`/classes/${classId}/students/${studentId}/labels`)
  }

  updateStudentLabels(classId: number, studentId: number, labels: string[]): APIResponse<void> {
    return super.postWithNoExpectedResponse(
      `/classes/${classId}/students/${studentId}/labels`,
      labels,
    )
  }
}
