<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
import { useSftp } from '~/composables/useSftp'
import { useSessionStore } from '~/stores/session.store'

const props = defineProps<{
  sessionId: string | null
}>()

const sessions = useSessionStore()
const sessionIdRef = computed(() => props.sessionId)
const {
  entries, currentPath, fileContent,
  connect, disconnect, list, readFile, writeFile, mkdir, rename, remove, download, upload,
} = useSftp(sessionIdRef)

// Track the terminal's current working directory from the session store
const sessionCwd = computed(() => {
  if (!props.sessionId) return null
  return sessions.sessions.find(s => s.id === props.sessionId)?.cwd ?? null
})

// Follow terminal CWD changes
watch(sessionCwd, (newCwd, oldCwd) => {
  if (newCwd && newCwd !== oldCwd && newCwd !== currentPath.value) {
    list(newCwd)
  }
})

const width = ref(260)
const isDragging = ref(false)
const newFolderName = ref('')
const showNewFolderInput = ref(false)
const renameTarget = ref<string | null>(null)
const renameTo = ref('')
const fileInput = ref<HTMLInputElement | null>(null)

// Drag-and-drop state
const dragOver = ref(false)

// Fullscreen editor overlay state
const editorOverlay = ref(false)
const editorFilePath = ref('')
const editorContainer = ref<HTMLElement | null>(null)
let editorInstance: any = null
let editorMonaco: any = null
let editorOriginalContent = ''
const editorDirty = ref(false)
const editorSavedMsg = ref(false)
const editorLang = ref('plaintext')

function triggerUpload() {
  fileInput.value?.click()
}

function handleFileSelected(event: Event) {
  const input = event.target as HTMLInputElement
  const files = input.files
  if (!files?.length) return
  uploadFiles(files)
  input.value = ''
}

function uploadFiles(files: FileList | File[]) {
  for (const file of files) {
    const reader = new FileReader()
    reader.onload = () => {
      const base64 = (reader.result as string).split(',')[1]
      const destPath = `${currentPath.value === '/' ? '' : currentPath.value}/${file.name}`
      upload(destPath, base64)
    }
    reader.readAsDataURL(file)
  }
}

// Drag-and-drop handlers
function handleDragOver(e: DragEvent) {
  e.preventDefault()
  e.stopPropagation()
  if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy'
  dragOver.value = true
}

function handleDragLeave(e: DragEvent) {
  e.preventDefault()
  e.stopPropagation()
  dragOver.value = false
}

function handleDrop(e: DragEvent) {
  e.preventDefault()
  e.stopPropagation()
  dragOver.value = false
  const files = e.dataTransfer?.files
  if (files?.length) {
    uploadFiles(files)
  }
}

onMounted(() => {
  connect()
  list('~')
})

onBeforeUnmount(() => {
  editorInstance?.dispose()
})

function navigateTo(path: string) {
  list(path)
}

function goUp() {
  const parts = currentPath.value.split('/').filter(Boolean)
  parts.pop()
  list(parts.length ? '/' + parts.join('/') : '/')
}

function handleOpenFile(path: string) {
  readFile(path)
}

const langMap: Record<string, string> = {
  ts: 'typescript', js: 'javascript', json: 'json', py: 'python',
  sh: 'shell', bash: 'shell', yml: 'yaml', yaml: 'yaml',
  md: 'markdown', html: 'html', css: 'css', xml: 'xml',
  go: 'go', rs: 'rust', rb: 'ruby', php: 'php',
  conf: 'ini', cfg: 'ini', ini: 'ini', toml: 'ini',
  sql: 'sql', dockerfile: 'dockerfile',
}

// Watch for file content and open fullscreen editor
watch(fileContent, async (fc) => {
  if (!fc) return

  editorFilePath.value = fc.path
  editorOriginalContent = fc.content
  editorDirty.value = false
  editorSavedMsg.value = false

  const ext = fc.path.split('.').pop() || ''
  editorLang.value = langMap[ext] || 'plaintext'

  // Clear fileContent so the file tree stays visible underneath
  fileContent.value = null

  // Show overlay and mount Monaco
  editorOverlay.value = true
  await nextTick()

  if (!editorContainer.value) return

  if (!editorMonaco) {
    editorMonaco = await import('monaco-editor')
  }

  // Dispose previous instance if any
  editorInstance?.dispose()

  editorInstance = editorMonaco.editor.create(editorContainer.value, {
    value: editorOriginalContent,
    language: editorLang.value,
    theme: 'vs-dark',
    fontSize: 13,
    fontFamily: "'JetBrains Mono', 'Fira Code', monospace",
    minimap: { enabled: true },
    scrollBeyondLastLine: false,
    automaticLayout: true,
  })

  editorInstance.onDidChangeModelContent(() => {
    editorDirty.value = editorInstance.getValue() !== editorOriginalContent
  })

  // Ctrl+S to save
  editorInstance.addCommand(
    editorMonaco.KeyMod.CtrlCmd | editorMonaco.KeyCode.KeyS,
    () => editorSave()
  )

  // Esc to close
  editorInstance.addCommand(
    editorMonaco.KeyCode.Escape,
    () => editorClose()
  )

  editorInstance.focus()
})

function editorSave() {
  if (!editorInstance) return
  const val = editorInstance.getValue()
  writeFile(editorFilePath.value, val)
  editorOriginalContent = val
  editorDirty.value = false
  editorSavedMsg.value = true
  setTimeout(() => { editorSavedMsg.value = false }, 2000)
}

function editorClose() {
  if (editorDirty.value) {
    if (!confirm('You have unsaved changes. Close anyway?')) return
  }
  editorOverlay.value = false
  editorInstance?.dispose()
  editorInstance = null
}

function handleDelete(path: string) {
  if (confirm(`Delete ${path}?`)) {
    remove(path)
    list(currentPath.value)
  }
}

function handleRename(oldPath: string) {
  renameTarget.value = oldPath
  renameTo.value = oldPath.split('/').pop() || ''
}

function confirmRename() {
  if (!renameTarget.value || !renameTo.value) return
  const dir = renameTarget.value.split('/').slice(0, -1).join('/')
  rename(renameTarget.value, `${dir}/${renameTo.value}`)
  renameTarget.value = null
  list(currentPath.value)
}

function createFolder() {
  if (!newFolderName.value) return
  mkdir(`${currentPath.value === '/' ? '' : currentPath.value}/${newFolderName.value}`)
  newFolderName.value = ''
  showNewFolderInput.value = false
  list(currentPath.value)
}

function startResize(event: MouseEvent) {
  isDragging.value = true
  const startX = event.clientX
  const startWidth = width.value

  const onMove = (e: MouseEvent) => {
    width.value = Math.max(180, Math.min(480, startWidth + (e.clientX - startX)))
  }
  const onUp = () => {
    isDragging.value = false
    window.removeEventListener('mousemove', onMove)
    window.removeEventListener('mouseup', onUp)
  }
  window.addEventListener('mousemove', onMove)
  window.addEventListener('mouseup', onUp)
}

// Breadcrumb segments from currentPath
const breadcrumbs = computed(() => {
  const parts = currentPath.value.split('/').filter(Boolean)
  return [
    { name: '/', path: '/' },
    ...parts.map((part, i) => ({
      name: part,
      path: '/' + parts.slice(0, i + 1).join('/'),
    })),
  ]
})
</script>

<template>
  <div class="flex h-full" :style="{ width: width + 'px' }">
    <div
      class="flex flex-col h-full bg-gray-900 border-r border-gray-800 overflow-hidden flex-1"
      @dragover="handleDragOver"
      @dragleave="handleDragLeave"
      @drop="handleDrop"
    >
      <!-- Toolbar -->
      <div class="px-2 py-1.5 border-b border-gray-800 shrink-0">
        <!-- Breadcrumbs -->
        <div class="flex items-center gap-1 text-xs text-gray-500 overflow-x-auto mb-1">
          <button
            v-for="(crumb, i) in breadcrumbs"
            :key="crumb.path"
            class="hover:text-wraith-400 shrink-0"
            @click="navigateTo(crumb.path)"
          >{{ crumb.name }}</button>
          <template v-if="breadcrumbs.length > 1">
            <span v-for="(_, i) in breadcrumbs.slice(1)" :key="i" class="text-gray-700">/</span>
          </template>
        </div>
        <!-- Actions -->
        <div class="flex items-center gap-1">
          <button
            v-if="currentPath !== '/'"
            @click="goUp"
            class="text-xs text-gray-500 hover:text-gray-300 px-1.5 py-0.5 rounded hover:bg-gray-800"
            title="Go up"
          >Up</button>
          <button
            @click="list(currentPath)"
            class="text-xs text-gray-500 hover:text-gray-300 px-1.5 py-0.5 rounded hover:bg-gray-800"
            title="Refresh"
          >Refresh</button>
          <button
            @click="showNewFolderInput = !showNewFolderInput"
            class="text-xs text-gray-500 hover:text-wraith-400 px-1.5 py-0.5 rounded hover:bg-gray-800"
            title="New folder"
          >+ Folder</button>
          <button
            @click="triggerUpload"
            class="text-xs text-gray-500 hover:text-wraith-400 px-1.5 py-0.5 rounded hover:bg-gray-800"
            title="Upload file"
          >Upload</button>
          <input ref="fileInput" type="file" multiple class="hidden" @change="handleFileSelected" />
        </div>
        <!-- New folder input -->
        <div v-if="showNewFolderInput" class="flex gap-1 mt-1">
          <input
            v-model="newFolderName"
            class="flex-1 text-xs bg-gray-800 border border-gray-700 rounded px-1.5 py-0.5 text-white"
            placeholder="Folder name"
            @keyup.enter="createFolder"
            autofocus
          />
          <button @click="createFolder" class="text-xs text-wraith-400 hover:text-wraith-300">OK</button>
          <button @click="showNewFolderInput = false" class="text-xs text-gray-500">x</button>
        </div>
        <!-- Rename input -->
        <div v-if="renameTarget" class="flex gap-1 mt-1">
          <input
            v-model="renameTo"
            class="flex-1 text-xs bg-gray-800 border border-gray-700 rounded px-1.5 py-0.5 text-white"
            placeholder="New name"
            @keyup.enter="confirmRename"
            autofocus
          />
          <button @click="confirmRename" class="text-xs text-wraith-400 hover:text-wraith-300">OK</button>
          <button @click="renameTarget = null" class="text-xs text-gray-500">x</button>
        </div>
      </div>

      <!-- File tree with drag-and-drop overlay -->
      <div class="flex-1 min-h-0 overflow-hidden relative">
        <!-- Drag overlay -->
        <div
          v-if="dragOver"
          class="absolute inset-0 z-10 flex items-center justify-center bg-wraith-600/10 border-2 border-dashed border-wraith-500 rounded pointer-events-none"
        >
          <span class="text-wraith-400 text-sm font-medium">Drop files to upload</span>
        </div>

        <SftpFileTree
          :entries="entries"
          :current-path="currentPath"
          @navigate="navigateTo"
          @open-file="handleOpenFile"
          @download="download"
          @delete="handleDelete"
          @rename="handleRename"
        />
      </div>
    </div>

    <!-- Resize handle -->
    <div
      class="w-1 bg-transparent hover:bg-wraith-500 cursor-col-resize transition-colors shrink-0"
      @mousedown="startResize"
    />

    <!-- Fullscreen Monaco editor overlay -->
    <Teleport to="body">
      <div
        v-if="editorOverlay"
        class="fixed inset-0 z-[99999] flex flex-col bg-[#0a0a0f]"
      >
        <!-- Editor toolbar -->
        <div class="h-9 bg-[#1a1a2e] border-b border-[#2a2a3e] flex items-center justify-between px-3 shrink-0">
          <span class="text-xs text-gray-500 font-mono truncate max-w-[60%]" :title="editorFilePath">{{ editorFilePath }}</span>
          <div class="flex items-center gap-2">
            <span v-if="editorDirty" class="text-xs text-amber-400">unsaved</span>
            <span v-if="editorSavedMsg" class="text-xs text-green-400">Saved!</span>
            <button
              @click="editorSave"
              :disabled="!editorDirty"
              class="px-3 py-1 rounded text-xs"
              :class="editorDirty ? 'bg-[#e94560] hover:bg-[#c23152] text-white cursor-pointer' : 'bg-[#e94560]/40 text-white/40 cursor-default'"
            >Save</button>
            <button
              @click="editorClose"
              class="px-3 py-1 rounded text-xs bg-gray-700 hover:bg-gray-600 text-gray-300"
            >Close</button>
          </div>
        </div>

        <!-- Monaco mount point -->
        <div ref="editorContainer" class="flex-1" />

        <!-- Status bar -->
        <div class="h-6 bg-[#1a1a2e] border-t border-[#2a2a3e] flex items-center px-3 shrink-0">
          <span class="text-[11px] text-gray-500">{{ editorLang }}</span>
          <span class="text-[11px] text-gray-600 ml-3">Ctrl+S save | Esc close</span>
        </div>
      </div>
    </Teleport>
  </div>
</template>
