<template>
  <AppShell>
    <NSpin :show="loading">
      <div
        v-if="issue"
        class="space-y-6"
      >
        <!-- Header -->
        <div class="flex items-center justify-between">
          <div class="flex items-center gap-3">
            <span class="text-gray-400 font-mono text-sm">#{{ issue.number }}</span>
            <h1 class="text-2xl font-semibold">
              {{ issue.title }}
            </h1>
            <NTag
              :type="issue.status === 'open' ? 'success' : 'default'"
              size="small"
            >
              {{ issue.status === 'open' ? '开放' : '关闭' }}
            </NTag>
          </div>
          <div class="flex items-center gap-2">
            <NButton
              v-if="issue.status === 'open'"
              type="warning"
              size="small"
              :loading="toggling"
              @click="onClose"
            >
              关闭 Issue
            </NButton>
            <NButton
              v-else
              type="primary"
              size="small"
              :loading="toggling"
              @click="onReopen"
            >
              重新开放
            </NButton>
            <NButton
              size="small"
              @click="router.back()"
            >
              返回
            </NButton>
          </div>
        </div>

        <!-- Mount card -->
        <NCard title="挂载">
          <NSelect
            :value="mountedRequirementNumber"
            :options="requirementOptions"
            placeholder="未挂载"
            clearable
            @update:value="onMountChange"
          />
        </NCard>

        <!-- Workspace card -->
        <NCard title="工作区">
          <NSelect
            :value="issue.workspace_id"
            :options="workspaceOptions"
            placeholder="未关联"
            clearable
            @update:value="onWorkspaceChange"
          />
        </NCard>

        <!-- Assignee card -->
        <NCard title="指派">
          <div class="flex items-center gap-4">
            <span class="text-sm text-gray-600">
              {{ issue.assignee_id ? `已指派：${issue.assignee_id}` : '暂未指派' }}
            </span>
            <div class="flex items-center gap-2">
              <NButton
                size="small"
                :loading="assigning"
                @click="onAssignToMe"
              >
                指派给我
              </NButton>
              <NButton
                v-if="issue.assignee_id"
                size="small"
                :loading="assigning"
                @click="onUnassign"
              >
                取消指派
              </NButton>
            </div>
          </div>
        </NCard>

        <!-- Description card -->
        <NCard title="描述">
          <p
            v-if="issue.description"
            class="text-gray-700 whitespace-pre-wrap"
          >
            {{ issue.description }}
          </p>
          <p
            v-else
            class="text-gray-400 text-sm"
          >
            暂无描述
          </p>
        </NCard>
      </div>

      <div
        v-else-if="!loading"
        class="text-gray-400 text-sm py-8 text-center"
      >
        Issue 不存在或无权访问。
      </div>
    </NSpin>
  </AppShell>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NCard, NButton, NTag, NSpin, NSelect } from 'naive-ui'
import AppShell from '@/layouts/AppShell.vue'
import { projectsApi } from '@/api/projects'
import { useAuthStore } from '@/stores/auth'
import { useWorkspacesStore } from '@/stores/workspaces'
import type { Issue, Requirement } from '@/api/projects'

const route = useRoute()
const router = useRouter()
const auth = useAuthStore()
const wsStore = useWorkspacesStore()

const slug = route.params.slug as string
const number = Number(route.params.number)

const loading = ref(false)
const toggling = ref(false)
const assigning = ref(false)

const issue = ref<Issue | null>(null)
const requirements = ref<Requirement[]>([])

const requirementOptions = computed(() =>
  requirements.value.map((r) => ({ label: `R-${r.number}: ${r.title}`, value: r.number })),
)

const workspaceOptions = computed(() =>
  wsStore.list.map((w) => ({ label: `${w.name} (${w.slug})`, value: w.id })),
)

const mountedRequirementNumber = computed<number | null>(() => {
  if (!issue.value?.requirement_id) return null
  const req = requirements.value.find((r) => r.id === issue.value!.requirement_id)
  return req?.number ?? null
})

async function fetchData() {
  loading.value = true
  try {
    const [fetchedIssue, reqs] = await Promise.all([
      projectsApi.getIssue(slug, number),
      projectsApi.listRequirements(slug),
      wsStore.fetchByProject(slug),
    ])
    issue.value = fetchedIssue
    requirements.value = reqs.items
  } finally {
    loading.value = false
  }
}

async function onMountChange(v: number | null) {
  if (!issue.value) return
  issue.value = await projectsApi.updateIssue(slug, number, { requirement_number: v })
}

async function onWorkspaceChange(v: string | null) {
  if (!issue.value) return
  issue.value = await projectsApi.updateIssue(slug, number, { workspace_id: v })
}

async function onClose() {
  toggling.value = true
  try {
    await projectsApi.closeIssue(slug, number)
    issue.value = await projectsApi.getIssue(slug, number)
  } finally {
    toggling.value = false
  }
}

async function onReopen() {
  toggling.value = true
  try {
    await projectsApi.reopenIssue(slug, number)
    issue.value = await projectsApi.getIssue(slug, number)
  } finally {
    toggling.value = false
  }
}

async function onAssignToMe() {
  if (!issue.value) return
  const userId = auth.user?.id
  if (!userId) return
  assigning.value = true
  try {
    issue.value = await projectsApi.assignIssue(slug, number, userId)
  } finally {
    assigning.value = false
  }
}

async function onUnassign() {
  if (!issue.value) return
  assigning.value = true
  try {
    issue.value = await projectsApi.assignIssue(slug, number, null)
  } finally {
    assigning.value = false
  }
}

onMounted(fetchData)
</script>
