<script setup>
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { Plus, TicketCheck, Pencil, Trash2, RefreshCw, CalendarDays, Flag, Play, Check, Archive, RotateCcw, X, Bug, Sparkles, Wrench, ListChecks, ImagePlus } from 'lucide-vue-next'
import { call, notifyTasksChanged, onTasksChanged } from '../api'
import { useAppStore } from '../store'
import MarkdownView from '../components/MarkdownView.vue'
import DueQuickPick from '../components/DueQuickPick.vue'
import DatePicker from '../components/DatePicker.vue'
import LifecycleTimeline from '../components/LifecycleTimeline.vue'
import { useMdEditor } from '../mdeditor'

const route = useRoute()
const router = useRouter()
const { t } = useI18n()
const store = useAppStore()
const tickets = ref([])
const statusFilter = ref('all')
const projectFilter = ref(0)
const modal = ref(false)
const saving = ref(false)
const error = ref('')
const form = reactive({ id: 0, title: '', description: '', type: 'task', projectId: 0, startAt: '', dueAt: '', priority: 'medium', status: 'open' })
const current = ref(null) // 正在编辑的原始条目（时间线展示已保存的轨迹）
const md = useMdEditor(form, 'description', e => { error.value = errText(e) })

const statuses = ['open', 'in_progress', 'resolved', 'closed']
const typeIcon = { feature: Sparkles, bug: Bug, task: ListChecks, improvement: Wrench }
const filtered = computed(() => tickets.value.filter(x =>
  (statusFilter.value === 'all' || x.status === statusFilter.value) &&
  (!projectFilter.value || x.projectId === projectFilter.value)
))
const counts = computed(() => Object.fromEntries(['all', ...statuses].map(s => [s, s === 'all' ? tickets.value.length : tickets.value.filter(x => x.status === s).length])))
const overdue = x => x.dueAt && ['open', 'in_progress'].includes(x.status) && new Date(x.dueAt.length === 10 ? x.dueAt + 'T23:59' : x.dueAt) < new Date()
// 状态流转：开始处理 → 解决 → 关闭；已解决/已关闭可重新打开。
const flowActions = x => ({
  open: [{ key: 'in_progress', label: t('ticketFlow.start'), icon: Play }],
  in_progress: [{ key: 'resolved', label: t('ticketFlow.resolve'), icon: Check }],
  resolved: [{ key: 'closed', label: t('ticketFlow.close'), icon: Archive }, { key: 'open', label: t('ticketFlow.reopen'), icon: RotateCcw }],
  closed: [{ key: 'open', label: t('ticketFlow.reopen'), icon: RotateCcw }]
}[x.status] || [])

async function load() {
  tickets.value = await call('ListTickets', 'all', 0)
}
// 本页写入后广播（顶栏任务中心等同步刷新）；也接收其它入口的变更
async function reloadAndNotify() {
  await load()
  notifyTasksChanged()
}
function openModal(x) {
  Object.assign(form, x
    ? { id: x.id, title: x.title, description: x.description, type: x.type, projectId: x.projectId, startAt: x.startAt, dueAt: x.dueAt, priority: x.priority, status: x.status }
    : { id: 0, title: '', description: '', type: 'task', projectId: projectFilter.value || store.projects[0]?.id || 0, startAt: new Date().toISOString().slice(0, 10), dueAt: '', priority: 'medium', status: 'open' })
  current.value = x || null
  error.value = ''
  md.reset()
  modal.value = true
}
const errText = raw => {
  const code = ['TICKET_TITLE_REQUIRED', 'TICKET_PROJECT_REQUIRED', 'TICKET_SCHEDULE_REQUIRED', 'TICKET_SCHEDULE_INVALID', 'TICKET_STATUS_INVALID'].find(c => String(raw).includes(c))
  return code ? t(`errors.${code}`) : String(raw)
}
async function save() {
  if (saving.value) return
  saving.value = true
  error.value = ''
  try {
    await call('SaveTicket', { ...form, projectId: Number(form.projectId) || 0 })
    modal.value = false
    await reloadAndNotify()
  } catch (e) {
    error.value = errText(e)
  } finally {
    saving.value = false
  }
}
async function setStatus(x, status) {
  await call('SetTicketStatus', x.id, status)
  await reloadAndNotify()
}
async function remove(x) {
  if (!confirm(`${t('delete')} ${x.title}?`)) return
  await call('DeleteTicket', x.id)
  await reloadAndNotify()
}
// 深链 ?edit=id：任务中心/日历详情点“编辑”后直接弹出编辑框
function openEditFromQuery() {
  const id = Number(route.query.edit)
  if (!id) return
  router.replace('/tickets')
  const x = tickets.value.find(i => i.id === id)
  if (x) openModal(x)
}
onMounted(async () => {
  await load()
  openEditFromQuery()
})
watch(() => route.query.edit, v => { if (v) openEditFromQuery() })
const offTasks = onTasksChanged(load)
onUnmounted(() => offTasks())
</script>

<template>
  <div class="page tickets-page">
    <header class="page-head sticky-head">
      <div><h1>{{ t('tickets') }}</h1><p>{{ t('ticketsSubtitle') }}</p></div>
      <div class="actions">
        <button class="btn secondary" @click="load"><RefreshCw />{{ t('refresh') }}</button>
        <button class="btn primary" @click="openModal()"><Plus />{{ t('addTicket') }}</button>
      </div>
    </header>

    <div class="todo-toolbar">
      <div class="tabs compact ticket-tabs">
        <button v-for="s in ['all', ...statuses]" :key="s" :class="{ active: statusFilter === s }" @click="statusFilter = s">
          {{ s === 'all' ? t('allLogs') : t('ticketStatus.' + s) }}<i class="tab-count">{{ counts[s] }}</i>
        </button>
      </div>
      <select v-model.number="projectFilter" class="log-category">
        <option :value="0">{{ t('allProjects') }}</option>
        <option v-for="p in store.projects" :key="p.id" :value="p.id">{{ p.name }}</option>
      </select>
    </div>

    <section class="panel ticket-panel">
      <article v-for="x in filtered" :key="x.id" class="ticket-row" :class="[x.status, x.priority, { overdue: overdue(x) }]">
        <span class="ticket-type" :class="x.type" :title="t('ticketType.' + x.type)"><component :is="typeIcon[x.type] || ListChecks" /></span>
        <div class="ticket-main" @click="openModal(x)">
          <div class="ticket-title"><b>{{ x.title }}</b><span class="ticket-status" :class="x.status">{{ t('ticketStatus.' + x.status) }}</span></div>
          <MarkdownView v-if="x.description && x.description.trim() !== x.title.trim()" class="md-clamp ticket-desc" :source="x.description" />
          <div class="todo-meta">
            <span class="todo-chip">{{ x.projectName || ('#' + x.projectId) }}</span>
            <span class="todo-due" :class="{ overdue: overdue(x) }"><CalendarDays />{{ x.startAt.replace('T', ' ') }} → {{ x.dueAt.replace('T', ' ') }}</span>
            <span class="todo-priority" :class="x.priority"><Flag />{{ t('priority.' + x.priority) }}</span>
          </div>
        </div>
        <div class="ticket-actions">
          <button v-for="act in flowActions(x)" :key="act.key" class="btn secondary flow-btn" @click="setStatus(x, act.key)"><component :is="act.icon" />{{ act.label }}</button>
          <div class="icon-actions">
            <button :title="t('edit')" @click="openModal(x)"><Pencil /></button>
            <button :title="t('delete')" @click="remove(x)"><Trash2 /></button>
          </div>
        </div>
      </article>
      <div v-if="!filtered.length" class="empty"><TicketCheck />{{ t('noTickets') }}</div>
    </section>
  </div>

  <Teleport to="body">
    <div v-if="modal" class="overlay" @click.self="!saving && (modal = false)">
      <form class="modal modal-split" @submit.prevent="save">
        <header><h2>{{ form.id ? t('editTicket') : t('addTicket') }}</h2><button type="button" :disabled="saving" @click="modal = false"><X /></button></header>
        <div class="split-body">
          <div class="split-fields">
            <label>{{ t('ticketTitle') }}<input v-model="form.title" :disabled="saving" required /></label>
            <label>{{ t('relatedProject') }} *<select v-model.number="form.projectId" :disabled="saving" required><option :value="0" disabled>{{ t('selectProject') }}</option><option v-for="p in store.projects" :key="p.id" :value="p.id">{{ p.name }}</option></select></label>
            <label>{{ t('ticketTypeLabel') }}<select v-model="form.type" :disabled="saving"><option v-for="k in ['feature', 'bug', 'task', 'improvement']" :key="k" :value="k">{{ t('ticketType.' + k) }}</option></select></label>
            <label>{{ t('startDate') }} *<DatePicker v-model="form.startAt" :disabled="saving" :clearable="false" /></label>
            <label>{{ t('dueDate') }} *<DatePicker v-model="form.dueAt" :disabled="saving" :clearable="false" />
              <DueQuickPick v-model="form.dueAt" :disabled="saving" />
            </label>
            <div class="field-pair">
              <label>{{ t('priorityLabel') }}<select v-model="form.priority" :disabled="saving"><option value="low">{{ t('priority.low') }}</option><option value="medium">{{ t('priority.medium') }}</option><option value="high">{{ t('priority.high') }}</option></select></label>
              <label>{{ t('statusLabel') }}<select v-model="form.status" :disabled="saving"><option v-for="s in statuses" :key="s" :value="s">{{ t('ticketStatus.' + s) }}</option></select></label>
            </div>
            <LifecycleTimeline v-if="current" :history="current.history" :created-at="current.createdAt" :updated-at="current.updatedAt" :status="current.status" kind="ticket" />
          </div>
          <div class="split-editor">
            <div class="md-toolbar">
              <span class="md-field-label">{{ t('ticketDesc') }}</span>
              <div class="tabs compact">
                <button type="button" :class="{ active: !md.preview.value }" @click="md.preview.value = false">{{ t('mdEdit') }}</button>
                <button type="button" :class="{ active: md.preview.value }" @click="md.preview.value = true">{{ t('mdPreviewTab') }}</button>
              </div>
              <button type="button" class="btn secondary md-img-btn" :disabled="saving || md.uploading.value" @click="md.pickImage"><ImagePlus />{{ md.uploading.value ? t('mdInserting') : t('insertImage') }}</button>
            </div>
            <div class="md-editor">
              <textarea v-show="!md.preview.value" :ref="md.inputEl" v-model="form.description" :disabled="saving" :placeholder="t('mdPlaceholder')" @paste="md.onPaste" />
              <MarkdownView v-if="md.preview.value" class="md-preview-box" :source="form.description || t('mdEmpty')" />
            </div>
          </div>
        </div>
        <footer>
          <p v-if="error" class="form-error">{{ error }}</p>
          <button type="button" class="btn secondary" :disabled="saving" @click="modal = false">{{ t('cancel') }}</button>
          <button class="btn primary" :disabled="saving">{{ saving ? t('saving') : t('save') }}</button>
        </footer>
      </form>
    </div>
  </Teleport>
</template>
