import { defineStore } from 'pinia'
import { ref } from 'vue'
import { useApi } from '@/composables/useApi'
import { useInstancesStore } from '@/stores/instances'

export interface FileEntry {
  name: string
  path: string
  is_dir: boolean
  size: number
  modified: string
}

/**
 * Per-instance file browser store.
 * All operations target `/api/instances/{id}/...` — jailed to instance root.
 * Guard: if no current instance, list() sets error and bails out early.
 */
export const useFilesStore = defineStore('files', () => {
  const api = useApi()

  const cwd = ref<string>('')
  const entries = ref<FileEntry[]>([])
  const loading = ref(false)
  const error = ref<string | null>(null)

  /** Join two relative path segments with a single forward slash. */
  function joinPath(base: string, name: string): string {
    if (!base) return name
    return `${base}/${name}`
  }

  function currentId(): string | null {
    // Retrieve fresh from the store each call — avoids stale closure.
    return useInstancesStore().currentId
  }

  /** List a directory. Sets cwd + entries. Does NOT throw — sets error. */
  async function list(path: string): Promise<void> {
    const id = currentId()
    if (!id) {
      error.value = 'No instance — connect re-Agent'
      entries.value = []
      return
    }
    loading.value = true
    error.value = null
    try {
      const data = await api.get<{ entries: FileEntry[] }>(
        `/instances/${id}/files?path=${encodeURIComponent(path)}`,
      )
      cwd.value = path
      entries.value = data.entries ?? []
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to load directory'
    } finally {
      loading.value = false
    }
  }

  /** Read a text file. Returns content string. Throws on error (binary/too big/not found). */
  async function readFile(path: string): Promise<string> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    const data = await api.get<{ content: string }>(
      `/instances/${id}/file?path=${encodeURIComponent(path)}`,
    )
    return data.content ?? ''
  }

  /** Write / overwrite a text file. Throws on error. */
  async function writeFile(path: string, content: string): Promise<void> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    await api.put(`/instances/${id}/file`, { path, content })
  }

  /** Delete a file or directory (recursive). Throws on error. */
  async function del(path: string): Promise<void> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    await api.post(`/instances/${id}/files/delete`, { path })
  }

  /** Rename within the same parent. `name` is the bare new filename. Throws on error. */
  async function rename(path: string, name: string): Promise<void> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    await api.post(`/instances/${id}/files/rename`, { path, name })
  }

  /** Create a directory (and all missing ancestors). Throws on error. */
  async function mkdir(path: string): Promise<void> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    await api.post(`/instances/${id}/files/mkdir`, { path })
  }

  /** Create an empty file. Throws on error. */
  async function mkfile(path: string): Promise<void> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    await api.post(`/instances/${id}/files/mkfile`, { path })
  }

  /** Move a file or directory. Both paths are relative to the instance root. Throws on error. */
  async function move(path: string, dest: string): Promise<void> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    await api.post(`/instances/${id}/files/move`, { path, dest })
  }

  /** Copy a file or directory. Both paths are relative to the instance root. Throws on error. */
  async function copy(path: string, dest: string): Promise<void> {
    const id = currentId()
    if (!id) throw new Error('No instance selected')
    await api.post(`/instances/${id}/files/copy`, { path, dest })
  }

  return {
    cwd,
    entries,
    loading,
    error,
    joinPath,
    list,
    readFile,
    writeFile,
    del,
    rename,
    mkdir,
    mkfile,
    move,
    copy,
  }
})
