<script setup lang="ts">
import { ref, shallowRef, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { NButton } from 'naive-ui'
import { useAcpStore } from '@/stores/acp'
import { useAcpStream, type UseAcpStreamReturn } from '@/composables/useAcpStream'
import { useConfirm } from '@/composables/useConfirm'
import { acpApi, type AcpEvent, type PermissionRequest } from '@/api/acp'
import { useAuthStore } from '@/stores/auth'
import { workspacesApi } from '@/api/workspaces'
import SessionStatusBadge from '@/components/acp/SessionStatusBadge.vue'
import AgentEventCard from '@/components/acp/AgentEventCard.vue'
import PromptInput from '@/components/acp/PromptInput.vue'
import PermissionApprovalPanel from '@/components/acp/PermissionApprovalPanel.vue'
import CommitDialog from '@/views/workspaces/components/CommitDialog.vue'

const route = useRoute()
const store = useAcpStore()
const auth = useAuthStore()
const confirm = useConfirm()

const sessionId = computed(() => route.params.sessionId as string)

const stream = shallowRef<UseAcpStreamReturn | null>(null)
const eventsContainer = ref<HTMLElement | null>(null)
const errorMsg = ref<string | null>(null)

const events = computed<AcpEvent[]>(() => stream.value?.events.value ?? [])
const pendingPermissions = computed<PermissionRequest[]>(
  () => stream.value?.pendingPermissions.value ?? [],
)
// 后端通过 WS 推送的 client_error 帧（如越权 prompt / 方法不允许 / 转发失败）。
const streamError = computed<string | null>(() => stream.value?.errorMsg.value ?? null)
// 仅 session owner（或 admin）可决策；后端同样强制。
const canDecide = computed(
  () => auth.user?.is_admin === true || store.currentSession?.user_id === auth.user?.id,
)

async function approvePermission(reqID: string, optionId?: string) {
  try {
    await acpApi.permissions.approve(reqID, optionId)
  } catch (e) {
    errorMsg.value = e instanceof Error ? e.message : 'approve failed'
  }
}

async function denyPermission(reqID: string) {
  try {
    await acpApi.permissions.deny(reqID)
  } catch (e) {
    errorMsg.value = e instanceof Error ? e.message : 'deny failed'
  }
}

onMounted(async () => {
  try {
    await store.getSession(sessionId.value)
  } catch (e) {
    errorMsg.value = e instanceof Error ? e.message : 'failed to load session'
    return
  }
  stream.value = useAcpStream(sessionId.value)
  watch(
    () => events.value.length,
    async () => {
      await nextTick()
      if (eventsContainer.value) {
        eventsContainer.value.scrollTop = eventsContainer.value.scrollHeight
      }
    },
  )
})

onUnmounted(() => {
  stream.value?.close()
})

const lastPromptIndex = ref(-1)
const hasResponseAfterPrompt = ref(false)
const isPrompting = computed(() => lastPromptIndex.value >= 0 && !hasResponseAfterPrompt.value)

watch(
  () => events.value.length,
  () => {
    const evs = events.value
    if (lastPromptIndex.value < 0) {
      for (let i = evs.length - 1; i >= 0; i--) {
        if (evs[i].method === 'session/prompt' && evs[i].direction === 'in') {
          lastPromptIndex.value = i
          hasResponseAfterPrompt.value = false
          break
        }
      }
    }
    if (lastPromptIndex.value >= 0) {
      for (let i = lastPromptIndex.value + 1; i < evs.length; i++) {
        if (evs[i].kind === 'response') {
          hasResponseAfterPrompt.value = true
          break
        }
      }
    }
  },
)

function onPrompt(text: string) {
  const sess = store.currentSession
  if (!sess?.agent_session_id) {
    errorMsg.value = 'Agent not ready yet'
    return
  }
  errorMsg.value = null
  const ok = stream.value?.prompt(text, sess.agent_session_id)
  if (!ok) errorMsg.value = '发送失败：连接未就绪'
}

function onCancel() {
  const sess = store.currentSession
  if (!sess?.agent_session_id) return
  const ok = stream.value?.cancel(sess.agent_session_id)
  if (!ok) errorMsg.value = '取消失败：连接未就绪'
}

async function terminate() {
  const ok = await confirm('Terminate this session?')
  if (!ok) return
  try {
    await store.terminateSession(sessionId.value)
  } catch (e) {
    errorMsg.value = e instanceof Error ? e.message : 'terminate failed'
  }
}

const sessionStatus = computed(
  () => stream.value?.sessionStatus.value ?? store.currentSession?.status ?? 'starting',
)

// ===== 提交代码：复用 workspace 的 CommitDialog =====
// session 行只存 is_main_worktree + branch（无 worktree_id），因此：
//   - main worktree → target=main，targetId=workspace_id
//   - 子 worktree   → 按 branch 在该 workspace 的 worktrees 中解析出 id
const commitTarget = ref<{ target: 'main' | 'worktree'; targetId: string } | null>(null)

async function openCommit() {
  const sess = store.currentSession
  if (!sess) return
  errorMsg.value = null
  if (sess.is_main_worktree) {
    commitTarget.value = { target: 'main', targetId: sess.workspace_id }
    return
  }
  try {
    const worktrees = await workspacesApi.listWorktrees(sess.workspace_id)
    const wt = worktrees.find((w) => w.branch === sess.branch)
    if (!wt) {
      errorMsg.value = '未找到该会话对应的 worktree'
      return
    }
    commitTarget.value = { target: 'worktree', targetId: wt.id }
  } catch (e) {
    errorMsg.value = e instanceof Error ? e.message : '加载 worktree 失败'
  }
}
</script>

<template>
  <div class="flex flex-col h-full">
    <!-- Top bar -->
    <div class="flex items-center justify-between px-4 py-2 border-b">
      <div class="space-x-3 text-sm">
        <span class="font-mono">{{ store.currentSession?.branch }}</span>
        <span class="text-gray-500">·</span>
        <span class="text-xs text-gray-500 font-mono truncate max-w-md inline-block align-middle">
          {{ store.currentSession?.cwd_path }}
        </span>
      </div>
      <div class="flex items-center gap-2">
        <SessionStatusBadge :status="sessionStatus" />
        <NButton text type="primary" size="small" @click="openCommit"> 提交代码 </NButton>
        <NButton
          v-if="sessionStatus === 'starting' || sessionStatus === 'running'"
          text
          type="error"
          size="small"
          @click="terminate"
        >
          Terminate
        </NButton>
      </div>
    </div>

    <p v-if="errorMsg" class="px-4 py-2 text-sm text-red-600 bg-red-50">
      {{ errorMsg }}
    </p>

    <!-- WS client_error 帧提示 -->
    <p v-if="streamError" class="px-4 py-2 text-sm text-red-700 bg-red-100">
      连接错误：{{ streamError }}
    </p>

    <!-- 待审批工具调用 -->
    <PermissionApprovalPanel
      :requests="pendingPermissions"
      :can-decide="canDecide"
      @approve="approvePermission"
      @deny="denyPermission"
    />

    <!-- Events stream -->
    <div ref="eventsContainer" class="flex-1 overflow-y-auto px-4 py-3 space-y-1">
      <AgentEventCard v-for="ev in events" :key="ev.id" :event="ev" />
      <div v-if="events.length === 0" class="text-center text-gray-400 py-8">
        Waiting for agent...
      </div>
    </div>

    <!-- Prompt input -->
    <div class="border-t px-4 py-3">
      <PromptInput
        :disabled="sessionStatus === 'crashed' || sessionStatus === 'exited'"
        :is-prompting="isPrompting"
        @send="onPrompt"
        @cancel="onCancel"
      />
    </div>

    <CommitDialog
      v-if="commitTarget"
      :target="commitTarget.target"
      :target-id="commitTarget.targetId"
      @close="commitTarget = null"
      @committed="commitTarget = null"
    />
  </div>
</template>
