export type DriveRootKind = "personal" | "org" | "mount" | "shared"

export type DriveView =
  | "files"
  | "shared"
  | "org"
  | "mount"
  | "recent"
  | "starred"
  | "trash"
  | "search"

/** Decode one URL path segment (safe for names with literal `%`). */
export function decodePathSegment(segment: string): string {
  try {
    return decodeURIComponent(segment.replace(/\+/g, " "))
  } catch {
    return segment
  }
}

function decodePathSegments(segments: string[]): string[] {
  return segments.map(decodePathSegment)
}

export function encodePathSegments(segments: string[]): string {
  return segments.map((s) => encodeURIComponent(decodePathSegment(s))).join("/")
}

export function driveRouteBase(routeRoot = "drive"): string {
  return `/${routeRoot}`
}

export function buildDriveFolderHref(
  view: Extract<DriveView, "files" | "shared" | "org" | "mount">,
  segments: string[],
  rootId?: string,
  routeRoot = "drive"
): string {
  const base = driveRouteBase(routeRoot)
  const decoded = decodePathSegments(segments)
  if (view === "org" && rootId) {
    if (decoded.length === 0) return `${base}/org/${encodeURIComponent(rootId)}`
    return `${base}/org/${encodeURIComponent(rootId)}/folders/${encodePathSegments(decoded)}`
  }
  if (view === "mount" && rootId) {
    if (decoded.length === 0) return `${base}/mounts/${encodeURIComponent(rootId)}`
    return `${base}/mounts/${encodeURIComponent(rootId)}/folders/${encodePathSegments(decoded)}`
  }
  if (decoded.length === 0) {
    return view === "shared" ? `${base}/shared` : base
  }
  const prefix = view === "shared" ? `${base}/shared/folders` : `${base}/folders`
  return `${prefix}/${encodePathSegments(decoded)}`
}

export interface DriveRouteState {
  view: DriveView
  pathSegments: string[]
  page: number
  fileId: string | null
  query: string
  rootId: string | null
}

export function parseDriveSegments(segments: string[] | undefined): DriveRouteState {
  const parts = segments ?? []
  if (parts.length === 0) {
    return { view: "files", pathSegments: [], page: 1, fileId: null, query: "", rootId: null }
  }
  const head = parts[0]
  if (head === "recent" || head === "starred" || head === "trash") {
    return { view: head, pathSegments: [], page: 1, fileId: null, query: "", rootId: null }
  }
  if (head === "org" && parts[1]) {
    const folderId = decodePathSegment(parts[1])
    const folderParts = parts.slice(2)
    if (folderParts[0] === "folders") {
      folderParts.shift()
      const pageIdx = folderParts.indexOf("page")
      let page = 1
      if (pageIdx >= 0 && folderParts[pageIdx + 1]) {
        page = Math.max(1, parseInt(folderParts[pageIdx + 1], 10) || 1)
        folderParts.splice(pageIdx, 2)
      }
      return {
        view: "org",
        pathSegments: decodePathSegments(folderParts),
        page,
        fileId: null,
        query: "",
        rootId: folderId,
      }
    }
    return { view: "org", pathSegments: [], page: 1, fileId: null, query: "", rootId: folderId }
  }
  if (head === "mounts" && parts[1]) {
    const mountId = decodePathSegment(parts[1])
    const folderParts = parts.slice(2)
    if (folderParts[0] === "folders") {
      folderParts.shift()
      const pageIdx = folderParts.indexOf("page")
      let page = 1
      if (pageIdx >= 0 && folderParts[pageIdx + 1]) {
        page = Math.max(1, parseInt(folderParts[pageIdx + 1], 10) || 1)
        folderParts.splice(pageIdx, 2)
      }
      return {
        view: "mount",
        pathSegments: decodePathSegments(folderParts),
        page,
        fileId: null,
        query: "",
        rootId: mountId,
      }
    }
    return { view: "mount", pathSegments: [], page: 1, fileId: null, query: "", rootId: mountId }
  }
  if (head === "shared") {
    const folderParts = parts.slice(1)
    let page = 1
    if (folderParts[0] === "folders") {
      folderParts.shift()
      const pageIdx = folderParts.indexOf("page")
      if (pageIdx >= 0 && folderParts[pageIdx + 1]) {
        page = Math.max(1, parseInt(folderParts[pageIdx + 1], 10) || 1)
        folderParts.splice(pageIdx, 2)
      }
      return {
        view: "shared",
        pathSegments: decodePathSegments(folderParts),
        page,
        fileId: null,
        query: "",
        rootId: null,
      }
    }
    return { view: "shared", pathSegments: [], page: 1, fileId: null, query: "", rootId: null }
  }
  if (head === "search") {
    return { view: "search", pathSegments: [], page: 1, fileId: null, query: "", rootId: null }
  }
  if (head === "edit" && parts[1]) {
    return {
      view: "files",
      pathSegments: [],
      page: 1,
      fileId: decodeURIComponent(parts[1]),
      query: "",
      rootId: null,
    }
  }
  if (head === "folders") {
    const folderParts = parts.slice(1)
    let page = 1
    const pageIdx = folderParts.indexOf("page")
    if (pageIdx >= 0 && folderParts[pageIdx + 1]) {
      page = Math.max(1, parseInt(folderParts[pageIdx + 1], 10) || 1)
      folderParts.splice(pageIdx, 2)
    }
    return {
      view: "files",
      pathSegments: decodePathSegments(folderParts),
      page,
      fileId: null,
      query: "",
      rootId: null,
    }
  }
  return {
    view: "files",
    pathSegments: decodePathSegments(parts),
    page: 1,
    fileId: null,
    query: "",
    rootId: null,
  }
}

export function buildDrivePath(state: DriveRouteState, routeRoot = "drive"): string {
  const base = driveRouteBase(routeRoot)
  if (state.view === "recent") return `${base}/recent`
  if (state.view === "starred") return `${base}/starred`
  if (state.view === "trash") return `${base}/trash`
  if (state.view === "search") return `${base}/search`
  if (state.view === "org" && state.rootId) {
    const folder = state.pathSegments.length
      ? `${base}/org/${encodeURIComponent(state.rootId)}/folders/${encodePathSegments(state.pathSegments)}`
      : `${base}/org/${encodeURIComponent(state.rootId)}`
    const pageSuffix = state.page > 1 ? `/page/${state.page}` : ""
    return `${folder}${pageSuffix}`
  }
  if (state.view === "mount" && state.rootId) {
    const folder = state.pathSegments.length
      ? `${base}/mounts/${encodeURIComponent(state.rootId)}/folders/${encodePathSegments(state.pathSegments)}`
      : `${base}/mounts/${encodeURIComponent(state.rootId)}`
    const pageSuffix = state.page > 1 ? `/page/${state.page}` : ""
    return `${folder}${pageSuffix}`
  }
  if (state.view === "shared") {
    const folder = state.pathSegments.length
      ? `${base}/shared/folders/${encodePathSegments(state.pathSegments)}`
      : `${base}/shared`
    const pageSuffix = state.page > 1 ? `/page/${state.page}` : ""
    return `${folder}${pageSuffix}`
  }
  if (state.fileId && state.view === "files") {
    return `${base}/edit/${encodeURIComponent(state.fileId)}`
  }
  const folder = state.pathSegments.length
    ? `${base}/folders/${encodePathSegments(state.pathSegments)}`
    : base
  const pageSuffix = state.page > 1 ? `/page/${state.page}` : ""
  return `${folder}${pageSuffix}`
}

export function folderPathFromSegments(segments: string[]): string {
  const decoded = decodePathSegments(segments)
  if (decoded.length === 0) return "/"
  return "/" + decoded.join("/")
}

export function parentFolderPathFromFilePath(filePath: string): string {
  const normalized = filePath.replace(/^\/+/, "").replace(/\/+$/, "")
  if (!normalized) return "/"
  const parts = normalized.split("/")
  if (parts.length <= 1) return "/"
  return "/" + parts.slice(0, -1).join("/")
}

function isSafeDriveReturnPath(path: string): boolean {
  if (!path.startsWith("/drive") && !path.startsWith("/demo/drive")) return false
  if (path.startsWith("//")) return false
  if (path.includes("://")) return false
  return true
}

/** Stable Nextcloud file id segment (numeric). */
export function isDriveFileIdSegment(value: string): boolean {
  return /^[1-9][0-9]*$/.test(value)
}

/** Rich-text editor URL — id-only, no returnTo query param. */
export function buildDriveDocsEditHref(fileId: string | number): string {
  return `/drive/docs/${String(fileId)}/edit`
}

/** UltiDraw (Excalidraw) editor URL — id-only. */
export function buildDriveDrawEditHref(fileId: string | number): string {
  return `/drive/draw/${String(fileId)}/edit`
}

export function buildDriveEditHref(filePath: string, returnTo?: string): string {
  const params = new URLSearchParams()
  if (returnTo && isSafeDriveReturnPath(returnTo)) {
    params.set("returnTo", returnTo)
  }
  const base = `/drive/edit/${encodeURIComponent(filePath)}`
  const qs = params.toString()
  return qs ? `${base}?${qs}` : base
}

/** Resolve back link from editor: prefer session returnTo, else explicit returnTo, else parent folder. */
export function resolveDriveEditReturnTo(
  returnTo: string | null | undefined,
  filePath: string,
  folderHref: (folderPath: string) => string,
  sessionReturnTo?: string | null
): string {
  if (sessionReturnTo && isSafeDriveReturnPath(sessionReturnTo)) return sessionReturnTo
  if (returnTo && isSafeDriveReturnPath(returnTo)) return returnTo
  return folderHref(parentFolderPathFromFilePath(filePath))
}

export function driveRootKindForView(view: DriveView): DriveRootKind {
  if (view === "org") return "org"
  if (view === "mount") return "mount"
  if (view === "shared") return "shared"
  return "personal"
}
