import { create } from 'zustand'
import { letterGradeFromAccuracy } from '../../lib/judgmentGrade'
import type { GameStatsStore } from './types'

function sanitizeCount(value: number): number {
  return Math.max(0, Math.floor(value))
}

function sanitizeScore(value: number): number {
  return Math.max(0, Math.floor(value))
}

function computeGrade(perfectHits: number, goodHits: number, misses: number): number {
  const totalHits = perfectHits + goodHits + misses
  if (totalHits === 0) return 0
  return (perfectHits * 100 + goodHits * 70) / totalHits
}

function withComputedValues(perfectHits: number, goodHits: number, misses: number) {
  const computedGrade = computeGrade(perfectHits, goodHits, misses)
  const computedGradeLetter = letterGradeFromAccuracy(computedGrade)
  return { computedGrade, computedGradeLetter }
}

const INITIAL_COUNTS = {
  perfectHits: 0,
  goodHits: 0,
  misses: 0,
}

const INITIAL_GRADE = withComputedValues(
  INITIAL_COUNTS.perfectHits,
  INITIAL_COUNTS.goodHits,
  INITIAL_COUNTS.misses,
)

export const useGameStatsStore = create<GameStatsStore>((set) => ({
  currentSong: null,
  score: 0,
  ...INITIAL_COUNTS,
  ...INITIAL_GRADE,

  setCurrentSong: (song) => {
    set({ currentSong: song })
  },

  setScore: (score) => {
    set({ score: sanitizeScore(score) })
  },

  addScore: (amount) => {
    set((state) => ({ score: sanitizeScore(state.score + amount) }))
  },

  addPerfectHit: () => {
    set((state) => {
      const perfectHits = state.perfectHits + 1
      return {
        perfectHits,
        ...withComputedValues(perfectHits, state.goodHits, state.misses),
      }
    })
  },

  addGoodHit: () => {
    set((state) => {
      const goodHits = state.goodHits + 1
      return {
        goodHits,
        ...withComputedValues(state.perfectHits, goodHits, state.misses),
      }
    })
  },

  addMiss: () => {
    set((state) => {
      const misses = state.misses + 1
      return {
        misses,
        ...withComputedValues(state.perfectHits, state.goodHits, misses),
      }
    })
  },

  setJudgments: ({ perfectHits, goodHits, misses }) => {
    const safePerfect = sanitizeCount(perfectHits)
    const safeGood = sanitizeCount(goodHits)
    const safeMisses = sanitizeCount(misses)
    set({
      perfectHits: safePerfect,
      goodHits: safeGood,
      misses: safeMisses,
      ...withComputedValues(safePerfect, safeGood, safeMisses),
    })
  },

  resetStats: () => {
    set((state) => ({
      score: 0,
      ...INITIAL_COUNTS,
      ...INITIAL_GRADE,
      currentSong: state.currentSong,
    }))
  },

  resetAll: () => {
    set({
      currentSong: null,
      score: 0,
      ...INITIAL_COUNTS,
      ...INITIAL_GRADE,
    })
  },
}))
