// 공통 포맷터 — 부수효과 없는 순수 함수만 작성

import type { TaskStatus } from '@/mock/relay.mock'

/**
 * 숫자를 한국 통화 표기 (예: 12345 → "12,345원")
 */
export function formatCurrency(value: number): string {
  return `${value.toLocaleString('ko-KR')}원`
}

/**
 * Date 또는 ISO 문자열을 'YYYY-MM-DD' 형식으로 변환
 */
export function formatDate(input: Date | string): string {
  const date = typeof input === 'string' ? new Date(input) : input
  if (Number.isNaN(date.getTime())) return ''
  const yyyy = date.getFullYear()
  const mm = String(date.getMonth() + 1).padStart(2, '0')
  const dd = String(date.getDate()).padStart(2, '0')
  return `${yyyy}-${mm}-${dd}`
}

/* ============================================================
 * 표시용 파생 값 — 백엔드 원시 데이터를 화면 라벨/색상으로 변환
 * (서버는 타임스탬프/카운트만 내려주고 여기서 계산한다)
 * ============================================================ */

/** ISO 문자열/Date 를 한국어 상대시간으로 (예: "2시간 전", "어제", "3일 전") */
export function relativeTimeKo(input: Date | string): string {
  const date = typeof input === 'string' ? new Date(input) : input
  if (Number.isNaN(date.getTime())) return ''
  const diffMs = Date.now() - date.getTime()
  const min = Math.floor(diffMs / 60_000)
  if (min < 1) return '방금'
  if (min < 60) return `${min}분 전`
  const hour = Math.floor(min / 60)
  if (hour < 24) return `${hour}시간 전`
  const day = Math.floor(hour / 24)
  if (day === 1) return '어제'
  if (day < 7) return `${day}일 전`
  const week = Math.floor(day / 7)
  if (week < 5) return `${week}주 전`
  return formatDate(date)
}

/** 진행률 정보 (완료/전체 → 퍼센트·단계·라벨) */
export interface ProgressInfo {
  pct: number
  level: 'done' | 'mid' | 'low'
  label: string
}

/** 완료/전체 수로 진행률 계산 */
export function progressOf(done: number, total: number): ProgressInfo {
  const pct = total > 0 ? Math.round((done / total) * 100) : 0
  const level: ProgressInfo['level'] = pct >= 90 ? 'done' : pct >= 40 ? 'mid' : 'low'
  const label = pct === 0 ? '시작 전' : `${pct}% 완료`
  return { pct, level, label }
}

/** 첨부 파일 종류 (배지 라벨/색상 키) */
export type FileKind = 'pdf' | 'zip' | 'doc' | 'img'

/** 파일명(확장자)으로 종류 파생 — 활동/댓글처럼 종류 정보가 없을 때 사용 */
export function attachmentKindOf(name: string): FileKind {
  const ext = name.split('.').pop()?.toLowerCase() ?? ''
  if (['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp'].includes(ext)) return 'img'
  if (ext === 'pdf') return 'pdf'
  if (['zip', 'rar', '7z', 'tar', 'gz'].includes(ext)) return 'zip'
  return 'doc'
}

/** 파일 종류별 배지 라벨 + 색상 클래스(.fi-* — 첨부 카드/활동/댓글 공통) */
export function fileBadge(kind: FileKind): { label: string; cls: string } {
  const map: Record<FileKind, { label: string; cls: string }> = {
    img: { label: 'IMG', cls: 'fi-img' },
    pdf: { label: 'PDF', cls: 'fi-pdf' },
    zip: { label: 'ZIP', cls: 'fi-zip' },
    doc: { label: 'DOC', cls: 'fi-doc' },
  }
  return map[kind]
}

/** 바이트 수를 사람이 읽기 쉬운 단위로 (예: 19293798 → "18.4 MB") */
export function formatBytes(bytes: number): string {
  if (!Number.isFinite(bytes) || bytes <= 0) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB']
  const exp = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1)
  const value = bytes / Math.pow(1024, exp)
  // B 는 정수, 그 외는 소수 1자리
  const text = exp === 0 ? String(Math.round(value)) : value.toFixed(1)
  return `${text} ${units[exp]}`
}

/* ============================================================
 * 업무(Task) 표시용 파생 값
 * ============================================================ */

const WEEKDAYS_KO = ['일', '월', '화', '수', '목', '금', '토']

/** 업무 상태 → 한국어 라벨 */
const TASK_STATUS_LABEL: Record<TaskStatus, string> = {
  todo: '할 일',
  prog: '진행 중',
  review: '승인 대기',
  done: '완료',
  changes: '수정 요청',
}
export function taskStatusLabel(status: TaskStatus): string {
  return TASK_STATUS_LABEL[status] ?? status
}

/** 'M월 D일' (예: '6월 8일') */
export function monthDayKo(input: Date | string): string {
  const d = typeof input === 'string' ? new Date(input) : input
  if (Number.isNaN(d.getTime())) return ''
  return `${d.getMonth() + 1}월 ${d.getDate()}일`
}

/** 활동 피드 날짜 그룹 라벨 (오늘 / 어제 / 이번 주 / 'M월 D일') */
export function dayGroupKo(input: Date | string): string {
  const d = typeof input === 'string' ? new Date(input) : input
  if (Number.isNaN(d.getTime())) return ''
  const startD = new Date(d.getFullYear(), d.getMonth(), d.getDate())
  const now = new Date()
  const startNow = new Date(now.getFullYear(), now.getMonth(), now.getDate())
  const days = Math.round((startNow.getTime() - startD.getTime()) / 86_400_000)
  if (days <= 0) return '오늘'
  if (days === 1) return '어제'
  if (days < 7) return '이번 주'
  return monthDayKo(d)
}

/** HTML 특수문자 이스케이프 — 활동 문구에 사용자 입력을 안전하게 삽입할 때 사용 */
export function escapeHtml(input: string): string {
  return input
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
}

/** D-day 강조 단계 (마감 없음/완료 시 '') */
export type DdayLevel = '' | 'urgent' | 'soon' | 'calm'

/** 업무 마감 정보(원시 dueDate + 완료여부 → 표시 라벨들) */
export interface TaskDueInfo {
  /** 전체 날짜 라벨 (예: '6월 18일 (목)') — 마감 없으면 '' */
  dateLabel: string
  /** D-day 라벨 (예: 'D-3', 'D-DAY', '2일 지남') — 마감 없으면 '' */
  dday: string
  /** 목록 행 라벨 (완료: '6월 9일 완료' / 진행: 'D-3' / 지남: '2일 지남') */
  listLabel: string
  /** 마감 지남 여부(완료 업무는 false) */
  overdue: boolean
  /** D-day 강조 단계 (urgent: 지남/임박, soon: 3일 내, calm: 그 외) */
  ddayLevel: DdayLevel
}

/** dueDate(ISO|null) + 완료여부로 마감 표시 정보 계산 */
export function taskDueInfo(dueDate: string | null, isDone: boolean): TaskDueInfo {
  if (!dueDate) {
    return { dateLabel: '', dday: '', listLabel: '', overdue: false, ddayLevel: '' }
  }
  const due = new Date(dueDate)
  if (Number.isNaN(due.getTime())) {
    return { dateLabel: '', dday: '', listLabel: '', overdue: false, ddayLevel: '' }
  }
  const dateLabel = `${due.getMonth() + 1}월 ${due.getDate()}일 (${WEEKDAYS_KO[due.getDay()]})`

  // 자정 기준 일 수 차이
  const startDue = new Date(due.getFullYear(), due.getMonth(), due.getDate())
  const now = new Date()
  const startNow = new Date(now.getFullYear(), now.getMonth(), now.getDate())
  const days = Math.round((startDue.getTime() - startNow.getTime()) / 86_400_000)

  if (isDone) {
    return {
      dateLabel,
      dday: '',
      listLabel: `${monthDayKo(due)} 완료`,
      overdue: false,
      ddayLevel: '',
    }
  }
  if (days < 0) {
    const passed = `${-days}일 지남`
    return { dateLabel, dday: passed, listLabel: passed, overdue: true, ddayLevel: 'urgent' }
  }
  const dday = days === 0 ? 'D-DAY' : `D-${days}`
  // 임박도: 1일 이내 urgent, 3일 이내 soon, 그 외 calm
  const ddayLevel: DdayLevel = days <= 1 ? 'urgent' : days <= 3 ? 'soon' : 'calm'
  return { dateLabel, dday, listLabel: dday, overdue: false, ddayLevel }
}
