import { ElMessage, ElMessageBox } from 'element-plus'
import { mapsApi } from '@/api/mapEdit'
import { reflectionApi } from '@/api/reflection'

export type SaveMode = 'new' | 'replace' | 'cancel'

/** 文件名安全的时间戳：yyyyMMdd_HHmmss */
export function formatSaveTimestamp(d = new Date()): string {
  const p = (n: number) => String(n).padStart(2, '0')
  return `${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}_${p(d.getHours())}${p(d.getMinutes())}${p(d.getSeconds())}`
}

/** 名称后追加修改日期。 */
export function defaultNewSaveName(baseName: string, d = new Date()): string {
  const trimmed = baseName.trim()
  if (!trimmed) return formatSaveTimestamp(d)
  return `${trimmed}_${formatSaveTimestamp(d)}`
}

function fileBaseName(path: string): string {
  const normalized = path.replace(/\\/g, '/')
  const file = normalized.slice(normalized.lastIndexOf('/') + 1)
  const dot = file.lastIndexOf('.')
  return dot >= 0 ? file.slice(0, dot) : file
}

/** 与源路径同目录拼接新文件名。 */
export function joinPathWithName(sourcePath: string, newBaseName: string, ext = '.json'): string {
  const normalized = sourcePath.replace(/\\/g, '/')
  const slash = normalized.lastIndexOf('/')
  const sep = sourcePath.includes('\\') ? '\\' : '/'
  // 统一用归一化后的斜杠下标取目录，再换回平台分隔符；避免混合分隔符(如 C:\foo/bar.json)算错目录。
  const dir = slash >= 0 ? normalized.slice(0, slash).replace(/\//g, sep) : ''
  const file = `${newBaseName}${ext}`
  return dir ? `${dir}${sep}${file}` : file
}

export async function resolveBaseProjectPath(): Promise<string | null> {
  try {
    const pf = await reflectionApi.getProjectFields()
    if (pf.lastLoadedPath?.trim()) return pf.lastLoadedPath.trim()
    if (pf.autoloadPath?.trim()) return pf.autoloadPath.trim()
  } catch {
    // ignore
  }
  return null
}

/** 解析当前正在使用的地图名（编辑页未带 ?map= 时兜底）。 */
export async function resolveCurrentMapName(): Promise<string> {
  try {
    const r = await mapsApi.list()
    const cur = r.maps.find((m) => m.isCurrent)
    if (cur?.name?.trim()) return cur.name.trim()
    if (r.currentFileName?.trim()) {
      return r.currentFileName.replace(/\.json$/i, '').trim()
    }
  } catch {
    // ignore
  }
  return ''
}

const SAVE_NAME_PATTERN = /^[^\\/:*?"<>|]+$/

/** 是否保存成新项目？否 = 在原项目基础上直接覆盖。 */
export async function promptSaveMode(): Promise<SaveMode> {
  try {
    await ElMessageBox.confirm(
      '是否保存成新项目？\n\n' +
        '· 否，在原项目基础上保存：名称不变，直接覆盖原文件\n' +
        '· 是，保存成新项目：在服务器另存（默认名称含修改日期）',
      '保存确认',
      {
        confirmButtonText: '是，保存成新项目',
        cancelButtonText: '否，在原项目基础上保存',
        distinguishCancelAndClose: true,
        type: 'info'
      }
    )
    return 'new'
  } catch (action) {
    if (action === 'cancel') return 'replace'
    return 'cancel'
  }
}

/** 弹窗输入另存名称，默认「原名_修改日期」。 */
export async function promptNewSaveName(
  title: string,
  baseName: string
): Promise<string | null> {
  try {
    const r = await ElMessageBox.prompt(`请输入${title}名称`, title, {
      inputValue: defaultNewSaveName(baseName),
      inputPattern: SAVE_NAME_PATTERN,
      inputErrorMessage: '名称不能包含 \\ / : * ? " < > | 等字符',
      confirmButtonText: '保存到服务器',
      cancelButtonText: '取消'
    })
    const picked = (r.value ?? '').trim()
    return picked || null
  } catch {
    return null
  }
}

/** 项目：在原路径上覆盖，或另存为新文件（同目录 + 新名称）。 */
export async function executeProjectSave(mode: SaveMode): Promise<string | null> {
  if (mode === 'cancel') return null

  if (mode === 'replace') {
    const r = await reflectionApi.saveProject()
    return r.path
  }

  const basePath = await resolveBaseProjectPath()
  const baseName = basePath ? fileBaseName(basePath) : 'project'
  const newName = await promptNewSaveName('保存成新项目', baseName)
  if (!newName) return null

  const targetPath = basePath
    ? joinPathWithName(basePath, newName)
    : `${newName}.json`
  const r = await reflectionApi.saveProject(targetPath)
  return r.path
}
