import { useMemo } from 'react'
import type { Code } from '../api/client'
import { useCodes } from './useCodes'

/** 원문자 ①(U+2460)부터 ⑳까지. 그 밖은 번호를 그대로 쓴다. */
const CIRCLED_BASE = 0x2460
const CIRCLED_MAX = 20

/**
 * 진행단계를 다루는 헬퍼. 단계 개수·라벨·구간·진행상태·KPI 임계값이 전부 코드표에서 온다.
 *
 * 예전에는 stages.ts에 12개 라벨 배열이 박혀 있어서 단계를 하나 늘리려면 백엔드 4곳,
 * 프론트 8곳을 같이 고쳐야 했다. 이제 코드표 한 줄이면 된다.
 */
export interface Stages {
  /** 등록된 단계 수. 지금은 13. */
  count: number
  /** [1, 2, ... count] */
  numbers: number[]
  /** 화면 표시명. 모르는 번호면 번호를 문자열로 돌려준다. */
  label(stage: number): string
  /** ①②③… 20을 넘으면 번호 문자열. */
  symbol(stage: number): string
  /** 단계가 속한 업무구간 key. 미지정(null)이면 null. */
  groupKey(stage: number | null): string | null
  /** 업무구간 목록(정렬순). 칸반 색과 필터가 쓴다. */
  groups: Code[]
  /** 업무구간의 tone. 모르면 null. */
  groupTone(key: string | null): string | null
  /** 진행상태 - 'applied' | 'active' | 'done'. 단계 미지정이면 null. */
  progressOf(stage: number | null): string | null
  /** 이 KPI에 집계하기 시작하는 단계 번호. 지정이 없으면 null. */
  kpiThreshold(kpi: string): number | null
  /** 해당 단계가 이 KPI 집계 대상인지(임계값 이상인지). */
  countsToward(kpi: string, stage: number | null): boolean
}

export function useStages(): Stages {
  const stageCodes = useCodes('STAGE')
  const groups = useCodes('STAGE_GROUP')

  return useMemo(() => {
    const byNumber = new Map<number, Code>()
    for (const code of stageCodes) {
      byNumber.set(Number(code.code), code)
    }
    const numbers = stageCodes.map((code) => Number(code.code)).sort((a, b) => a - b)

    function attrOf(stage: number | null, key: string): string | null {
      if (stage === null) {
        return null
      }
      const value = byNumber.get(stage)?.attrs[key]
      return value == null ? null : String(value)
    }

    function kpiThreshold(kpi: string): number | null {
      for (const [number, code] of byNumber) {
        if (code.attrs.kpiFrom === kpi) {
          return number
        }
      }
      return null
    }

    return {
      count: numbers.length,
      numbers,
      label: (stage) => byNumber.get(stage)?.label ?? String(stage),
      symbol: (stage) =>
        stage >= 1 && stage <= CIRCLED_MAX
          ? String.fromCharCode(CIRCLED_BASE + stage - 1)
          : String(stage),
      groupKey: (stage) => attrOf(stage, 'groupKey'),
      groups,
      groupTone: (key) => {
        const found = groups.find((group) => group.code === key)
        const tone = found?.attrs.tone
        return tone == null ? null : String(tone)
      },
      progressOf: (stage) => attrOf(stage, 'progress'),
      kpiThreshold,
      countsToward: (kpi, stage) => {
        const from = kpiThreshold(kpi)
        return from !== null && stage !== null && stage >= from
      },
    }
  }, [stageCodes, groups])
}
