import { DEFAULT_PROJECT_ID, QUICK_PROJECT_ID, normalizeProjectId } from '@/lib/workspace'
import { i18n } from '@/i18n'

const PROJECT_REGISTRY_KEY = 'jgjs-project-registry-v1'

export interface ProjectMeta {
  id: string
  name: string
  createdAt: string
  updatedAt: string
  lastOpenedAt: string
}

type ProjectRegistryPayload = {
  projects: ProjectMeta[]
}

const nowIso = () => new Date().toISOString()
const lastEditedTouchAt = new Map<string, number>()

const defaultProjects = (): ProjectMeta[] => {
  return []
}

const sanitizeProject = (item: Partial<ProjectMeta> | null | undefined): ProjectMeta | null => {
  if (!item || typeof item !== 'object') return null
  const id = normalizeProjectId(item.id)
  const name = String(item.name || '').trim() || (
    id === QUICK_PROJECT_ID
      ? i18n.global.t('quickCalc.projectName')
      : i18n.global.t('tab.messages.projectNamePrefix', { id })
  )
  const createdAt = typeof item.createdAt === 'string' && item.createdAt ? item.createdAt : nowIso()
  const updatedAt = typeof item.updatedAt === 'string' && item.updatedAt ? item.updatedAt : createdAt
  const lastOpenedAt =
    typeof item.lastOpenedAt === 'string' && item.lastOpenedAt ? item.lastOpenedAt : updatedAt
  return { id, name, createdAt, updatedAt, lastOpenedAt }
}

const readPayload = (): ProjectRegistryPayload => {
  try {
    const raw = localStorage.getItem(PROJECT_REGISTRY_KEY)
    if (!raw) return { projects: defaultProjects() }
    const parsed = JSON.parse(raw) as Partial<ProjectRegistryPayload>
    const projects = Array.isArray(parsed?.projects)
      ? parsed.projects.map(item => sanitizeProject(item)).filter((item): item is ProjectMeta => Boolean(item))
      : []
    if (projects.length === 0) return { projects: defaultProjects() }
    return { projects }
  } catch {
    return { projects: defaultProjects() }
  }
}

const writePayload = (payload: ProjectRegistryPayload) => {
  localStorage.setItem(PROJECT_REGISTRY_KEY, JSON.stringify(payload))
}

export const listProjects = () => {
  const payload = readPayload()
  return payload.projects
    .filter(item => item.id !== QUICK_PROJECT_ID && item.id !== DEFAULT_PROJECT_ID)
    .slice()
    .sort((a, b) => new Date(b.lastOpenedAt).getTime() - new Date(a.lastOpenedAt).getTime())
}

export const upsertProject = (
  projectIdRaw: string,
  nameRaw?: string,
  options?: {
    touchUpdatedAt?: boolean
    touchLastOpenedAt?: boolean
  }
) => {
  const id = normalizeProjectId(projectIdRaw)
  if (id === QUICK_PROJECT_ID || id === DEFAULT_PROJECT_ID) return
  const name = String(nameRaw || '').trim()
  const payload = readPayload()
  const now = nowIso()
  const touchUpdatedAt = options?.touchUpdatedAt === true
  const touchLastOpenedAt = options?.touchLastOpenedAt !== false
  const index = payload.projects.findIndex(item => item.id === id)
  if (index < 0) {
    payload.projects.push({
      id,
      name: name || (
        id === QUICK_PROJECT_ID
          ? i18n.global.t('quickCalc.projectName')
          : i18n.global.t('tab.messages.projectNamePrefix', { id })
      ),
      createdAt: now,
      updatedAt: now,
      lastOpenedAt: now
    })
  } else {
    const current = payload.projects[index]
    payload.projects[index] = {
      ...current,
      name: name || current.name,
      updatedAt: touchUpdatedAt ? now : current.updatedAt,
      lastOpenedAt: touchLastOpenedAt ? now : current.lastOpenedAt
    }
  }
  writePayload(payload)
}

export const touchProjectEdited = (
  projectIdRaw: string,
  options?: {
    throttleMs?: number
  }
) => {
  const id = normalizeProjectId(projectIdRaw)
  if (id === QUICK_PROJECT_ID || id === DEFAULT_PROJECT_ID) return false
  const throttleMs = Math.max(0, Number(options?.throttleMs ?? 5000))
  const nowMs = Date.now()
  const lastTouch = lastEditedTouchAt.get(id) ?? 0
  if (throttleMs > 0 && nowMs - lastTouch < throttleMs) return false

  const payload = readPayload()
  const index = payload.projects.findIndex(item => item.id === id)
  if (index < 0) return false
  const now = nowIso()
  const current = payload.projects[index]
  payload.projects[index] = {
    ...current,
    updatedAt: now,
    lastOpenedAt: now
  }
  writePayload(payload)
  lastEditedTouchAt.set(id, nowMs)
  return true
}

export const createProject = (nameRaw?: string) => {
  const payload = readPayload()
  const now = nowIso()
  let id = ''
  do {
    id = normalizeProjectId(`p-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`)
  } while (payload.projects.some(item => item.id === id))
  const name = String(nameRaw || '').trim() || i18n.global.t('tab.messages.projectNamePrefix', { id: payload.projects.length + 1 })
  const project: ProjectMeta = { id, name, createdAt: now, updatedAt: now, lastOpenedAt: now }
  payload.projects.push(project)
  writePayload(payload)
  return project
}

export const deleteProject = (projectIdRaw: string) => {
  const id = normalizeProjectId(projectIdRaw)
  if (id === QUICK_PROJECT_ID || id === DEFAULT_PROJECT_ID) return false
  const payload = readPayload()
  const nextProjects = payload.projects.filter(item => item.id !== id)
  if (nextProjects.length === payload.projects.length) return false
  payload.projects = nextProjects
  writePayload(payload)
  return true
}
