import { computed, onMounted, onActivated, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useRoute, useRouter } from 'vue-router'
import { useServerList, type ServerBrief } from '@/composables/useServerList'
import { useSnackbar } from '@/composables/useSnackbar'
import { useFilesStore } from '@/stores/files'
import type { FileEntry } from '@/types/api'
import {
  buildRemoteBreadcrumbs,
  DEFAULT_FILES_ROOT,
  joinRemotePath,
  normalizeRemotePath,
  parentRemotePath,
  type RemoteBreadcrumbItem,
} from '@/utils/remotePath'
import { FILES_HINT_DISMISSED_KEY, FILES_LAST_SERVER_KEY } from './constants'

export function useFilesNavigation(options: {
  browse: (opts?: { force?: boolean; silent?: boolean }) => Promise<void | undefined>
  refreshFilesCapability: () => Promise<void>
  clearSelection: () => void
}) {
  const snackbar = useSnackbar()
  const route = useRoute()
  const router = useRouter()
  const { servers: serverList, loading: serversLoading, loadServers } = useServerList()
  const serverSearchQuery = ref('')

  function serverMatchesQuery(s: ServerBrief, q: string): boolean {
    return (
      s.name.toLowerCase().includes(q) ||
      (s.domain || '').toLowerCase().includes(q) ||
      (s.target_path || '').toLowerCase().includes(q) ||
      String(s.id).includes(q)
    )
  }

  const filteredServerList = computed(() => {
    const q = serverSearchQuery.value.toLowerCase().trim()
    let list = q ? serverList.value.filter((s) => serverMatchesQuery(s, q)) : serverList.value
    const selId = selectedServer.value
    if (selId != null && !list.some((s) => s.id === selId)) {
      const sel = serverList.value.find((s) => s.id === selId)
      if (sel) list = [sel, ...list]
    }
    return list
  })
  const store = useFilesStore()
  const {
    selectedServer,
    currentPath,
    pageReady,
    routeReady,
    initing,
    accessHintDismissed,
  } = storeToRefs(store)

  const breadcrumbs = computed((): RemoteBreadcrumbItem[] =>
    buildRemoteBreadcrumbs(currentPath.value),
  )

  const canGoUp = computed(() => parentRemotePath(currentPath.value) !== null)

  function defaultPathForServer(serverId: number | null): string {
    if (serverId == null) return DEFAULT_FILES_ROOT
    const srv = serverList.value.find((s) => s.id === serverId)
    const tp = srv?.target_path?.trim()
    return tp ? normalizeRemotePath(tp) : DEFAULT_FILES_ROOT
  }

  function pathFromRouteQuery(): string {
    const qPath = route.query.path
    if (typeof qPath === 'string' && qPath.trim()) {
      return normalizeRemotePath(qPath)
    }
    return defaultPathForServer(selectedServer.value)
  }

  function resolveInitialServerId(): number | null {
    const qServer = route.query.server_id
    if (qServer) {
      const id = Number(qServer)
      if (Number.isFinite(id) && serverList.value.some((s) => s.id === id)) return id
    }
    const stored = sessionStorage.getItem(FILES_LAST_SERVER_KEY)
    if (stored) {
      const id = Number(stored)
      if (Number.isFinite(id) && serverList.value.some((s) => s.id === id)) return id
    }
    return serverList.value[0]?.id ?? null
  }

  function navigateToPath(path: string) {
    if (!selectedServer.value) {
      snackbar('请先选择服务器', 'warning')
      return
    }
    currentPath.value = normalizeRemotePath(path)
    options.clearSelection()
    void options.browse()
  }

  function openEntry(item: FileEntry) {
    if (item.type === 'directory') {
      navigateToPath(joinRemotePath(currentPath.value, item.name))
      return
    }
    if (item.type === 'symlink') {
      const target = item.link_target?.trim()
      if (target?.startsWith('/')) {
        navigateToPath(target)
      } else {
        snackbar(
          target ? `符号链接 → ${target}` : '相对符号链接（请在终端中打开）',
          'info',
        )
      }
    }
  }

  function goUp() {
    const parent = parentRemotePath(currentPath.value)
    if (parent != null) navigateToPath(parent)
  }

  function onBreadcrumbClick(index: number) {
    const bc = breadcrumbs.value[index]
    if (bc && !bc.disabled) navigateToPath(bc.path)
  }

  function openInTerminal() {
    if (!selectedServer.value) return
    router.push({
      path: '/terminal',
      query: {
        server_id: String(selectedServer.value),
        path: currentPath.value || '/',
      },
    })
  }

  function onServerChange() {
    if (initing.value) return
    serverSearchQuery.value = ''
    if (selectedServer.value) {
      sessionStorage.setItem(FILES_LAST_SERVER_KEY, String(selectedServer.value))
    }
    store.invalidateCache()
    currentPath.value = defaultPathForServer(selectedServer.value)
    options.clearSelection()
    store.resetForServerChange()
    sessionStorage.removeItem(FILES_HINT_DISMISSED_KEY)
    void (async () => {
      await options.refreshFilesCapability()
      await options.browse({ force: true })
    })()
  }

  let navReady = false

  onMounted(async () => {
    initing.value = true
    try {
      await loadServers({ all: true })
      if (sessionStorage.getItem(FILES_HINT_DISMISSED_KEY)) {
        accessHintDismissed.value = true
      }
      if (!serverList.value.length) {
        snackbar('暂无可用服务器，请先在「服务器」页添加', 'warning')
        pageReady.value = true
        return
      }
      const initialId = resolveInitialServerId()
      if (initialId == null) {
        pageReady.value = true
        return
      }
      selectedServer.value = initialId
      const qPath = route.query.path
      currentPath.value =
        typeof qPath === 'string' && qPath
          ? normalizeRemotePath(qPath)
          : defaultPathForServer(initialId)
      await options.refreshFilesCapability()
      await options.browse()
      pageReady.value = true
      routeReady.value = true
    } finally {
      initing.value = false
      navReady = true
    }
  })

  onActivated(() => {
    if (!navReady || !pageReady.value || !selectedServer.value) return
    void options.browse({ silent: true })
  })

  watch(
    () => route.query.server_id,
    (id) => {
      if (!routeReady.value) return
      if (id && Number(id) !== selectedServer.value) {
        selectedServer.value = Number(id)
        currentPath.value = pathFromRouteQuery()
        store.resetForServerChange()
        void (async () => {
          await options.refreshFilesCapability()
          await options.browse({ force: true })
        })()
      }
    },
  )

  watch(
    () => route.query.path,
    () => {
      if (!routeReady.value || !selectedServer.value) return
      const next = pathFromRouteQuery()
      if (next !== normalizeRemotePath(currentPath.value)) {
        currentPath.value = next
        options.clearSelection()
        void options.browse()
      }
    },
  )

  return {
    serverList,
    filteredServerList,
    serverSearchQuery,
    serversLoading,
    breadcrumbs,
    canGoUp,
    navigateToPath,
    openEntry,
    goUp,
    onBreadcrumbClick,
    openInTerminal,
    onServerChange,
    defaultPathForServer,
  }
}
