import Colle from '#models/colle'
import Examiner from '#models/examiner'
import Room from '#models/room'
import Subject from '#models/subject'
import User from '#models/user'
import redis from '@adonisjs/redis/services/main'
export class ColleService {
  async getHealthyUntil(className: string) {
    const healtyUntil = await redis.get(`healthy_until_${className}`)
    return new Date(healtyUntil || '')
  }
  async getLastSync(className: string) {
    const lastSync = await redis.get(`last_sync_${className}`)
    return new Date(lastSync || '')
  }
  async getStudent(studentName: string, className: string) {
    // Find or create a student by name
    const { firstName, lastName } = this.splitNames(studentName)
    const student = await User.query()
      .where('first_name', firstName)
      .where('last_name', lastName)
      .where('class_name', className)
      .first()
    if (!student) {
      return User.create({ firstName, lastName, className })
    }
    return student
  }
  splitNames(fullName: string): { firstName: string; lastName: string } {
    const words = fullName.trim().split(/\s+/)
    let lastNameParts: string[] = []
    let i = 0
    // Collect all uppercase words at the start
    while (i < words.length && words[i] === words[i].toUpperCase()) {
      lastNameParts.push(words[i])
      i++
    }
    const lastName = lastNameParts.join(' ')
    const firstName = words.slice(i).join(' ')
    return { firstName, lastName }
  }
  async getExaminer(examinerName: string) {
    // Find or create an examiner by name
    const examiner = await Examiner.query().where('name', examinerName).first()
    if (!examiner) return Examiner.create({ name: examinerName })
    return examiner
  }
  async getSubject(subjectName: string) {
    // Find or create a subject by name
    const subject = await Subject.query().where('name', subjectName).first()
    if (!subject) return Subject.create({ name: subjectName })
    return subject
  }
  async getRoom(roomName: string) {
    // Find or create a room by name
    const room = await Room.query().where('name', roomName).first()
    if (!room) return Room.create({ name: roomName })
    return room
  }
  async getColles(student: User, startDate: string, endDate: string) {
    const classColles = await Colle.query()
      .preload('student')
      .preload('examiner')
      .preload('subject')
      .preload('room')
      .preload('attachments')
      .where('date', '>=', startDate)
      .where('date', '<=', endDate)
      .whereHas('student', (query) => {
        query.where('className', student.className)
      })
      // Filter only colles that have been graded
      .whereNotNull('grade')
      .orderBy('date', 'asc')
    const studentColles = await Colle.query()
      .preload('student')
      .preload('examiner')
      .preload('subject')
      .preload('room')
      .preload('attachments')
      .where('date', '>=', startDate)
      .where('date', '<=', endDate)
      .where('studentId', student.id)
      .orderBy('date', 'asc')
    // TODO: Favorite colles
    const favoriteColles = [] as Colle[]
    return {
      classColles,
      studentColles,
      favoriteColles,
      healthyUntil: await this.getHealthyUntil(student.className),
      lastSync: await this.getLastSync(student.className),
    }
  }
  // Pre-process HTML content to render LaTeX
  private removeTrailingLines(htmlString: string) {
    return htmlString.replace(/(
\s*)+$/gi, '').trim()
  }
  private extractLatexImages(html: string) {
    const imgRegex = /![]() ]+src="(https:\/\/latex\.codecogs\.com\/gif\.latex\?(=?.*?))"[^>]*>/g
    let parts = []
    let latexMatches: string[] = []
    let lastIndex = 0
    html.replace(imgRegex, (match, _, latex, index) => {
      parts.push(html.slice(lastIndex, index)) // Add HTML before image
      latexMatches.push(decodeURIComponent(latex)) // Extract and decode LaTeX
      lastIndex = index + match.length
      return ''
    })
    parts.push(html.slice(lastIndex)) // Add remaining HTML after last image
    return { parts, latexMatches }
  }
  prepareHtmlForRendering(html: string) {
    const strippedHtml = this.removeTrailingLines(html)
    const { parts, latexMatches } = this.extractLatexImages(strippedHtml)
    const outputHtml = parts
      .map((part, i) => {
        if (!latexMatches[i]) {
          return part
        }
        return `${part}$$${latexMatches[i]}$$`
      })
      .join('')
    // Remove all "\," from string
    const regex = /\\,/g
    return outputHtml.replace(regex, ' ')
  }
}
]+src="(https:\/\/latex\.codecogs\.com\/gif\.latex\?(=?.*?))"[^>]*>/g
    let parts = []
    let latexMatches: string[] = []
    let lastIndex = 0
    html.replace(imgRegex, (match, _, latex, index) => {
      parts.push(html.slice(lastIndex, index)) // Add HTML before image
      latexMatches.push(decodeURIComponent(latex)) // Extract and decode LaTeX
      lastIndex = index + match.length
      return ''
    })
    parts.push(html.slice(lastIndex)) // Add remaining HTML after last image
    return { parts, latexMatches }
  }
  prepareHtmlForRendering(html: string) {
    const strippedHtml = this.removeTrailingLines(html)
    const { parts, latexMatches } = this.extractLatexImages(strippedHtml)
    const outputHtml = parts
      .map((part, i) => {
        if (!latexMatches[i]) {
          return part
        }
        return `${part}$$${latexMatches[i]}$$`
      })
      .join('')
    // Remove all "\," from string
    const regex = /\\,/g
    return outputHtml.replace(regex, ' ')
  }
}