<!-- SPEC: MDTODO 三栏任务工作区. -->
<!-- Responsibility: Source Markdown 正文检查、inline edit、报告入口与 Workbench 交接。 -->

<script setup lang="ts">
import { ExternalLink, FileText, Pencil, Save, Trash2, X } from "lucide-vue-next";
import type {
  MdtodoTaskDetailRecord,
  MdtodoTaskLinkRecord,
  MdtodoTaskRecord,
  MdtodoTaskStatus,
} from "@/api";
import ApiErrorDiagnostic from "@/components/common/ApiErrorDiagnostic.vue";
import ContentViewer from "@/components/common/ContentViewer.vue";
import EmptyState from "@/components/common/EmptyState.vue";
import RefreshBoundary from "@/components/common/RefreshBoundary.vue";
import StatusBadge from "@/components/common/StatusBadge.vue";
import SectionFrame from "@/components/layout/SectionFrame.vue";
import { statusLabel } from "@/composables/mdtodo/useMdtodoDisplay";
import type { ApiError, ErrorDiagnostic, ProviderProfile } from "@/types";

const props = defineProps<{
  task: MdtodoTaskRecord | null;
  detail: MdtodoTaskDetailRecord | null;
  detailLoading: boolean;
  detailError: string | null;
  detailPartial: boolean;
  mutationDisabled: boolean;
  links: MdtodoTaskLinkRecord[];
  editingTitle: boolean;
  editingBody: boolean;
  editTitle: string;
  editStatus: MdtodoTaskStatus;
  editBody: string;
  deleteConfirm: boolean;
  mutationLoading: boolean;
  mutationMessage: string | null;
  mutationError: string | null;
  launchLoading: boolean;
  launchError: string | null;
  launchApiError: ApiError | null;
  launchDiagnostic: ErrorDiagnostic | null;
  launchEnabled: boolean;
  launchBlocker: string | null;
  providerProfile: ProviderProfile;
  providerOptions: Array<{
    value: ProviderProfile;
    label: string;
    configured?: boolean;
  }>;
}>();

const emit = defineEmits<{
  "update:editTitle": [value: string];
  "update:editStatus": [value: MdtodoTaskStatus];
  "update:editBody": [value: string];
  "update:providerProfile": [value: ProviderProfile];
  beginTitleEdit: [];
  cancelTitleEdit: [];
  saveTaskBasics: [];
  beginBodyEdit: [];
  cancelBodyEdit: [];
  saveTaskBody: [];
  deleteTask: [];
  cancelDelete: [];
  openReport: [link: MdtodoTaskLinkRecord];
  launchWorkbench: [];
}>();

function titleKeydown(event: KeyboardEvent): void {
  if (event.key === "Enter" || event.key === "F2") {
    event.preventDefault();
    emit("beginTitleEdit");
  }
}

function updateStatus(event: Event): void {
  emit("update:editStatus", (event.target as HTMLSelectElement).value as MdtodoTaskStatus);
  if (!props.editingTitle) emit("saveTaskBasics");
}
</script>

<template>
  <SectionFrame
    class="document-workspace"
    data-testid="mdtodo-task-detail"
    :title="task ? task.taskId || task.rxxId || '任务正文' : '任务正文'"
    :description="detail?.relativePath || '从任务树选择任务后读取 Source Markdown'"
    :body-padding="false"
  >
    <template #actions>
      <StatusBadge
        v-if="task"
        :status="task.status"
        :label="statusLabel(task.status)"
      />
      <span v-if="detailPartial" class="authority-warning">离线投影只读</span>
      <span v-else-if="task" class="authority-ready">Source Markdown</span>
    </template>

    <template v-if="task">
      <header class="document-command-strip">
        <div class="title-region">
          <div v-if="editingTitle" class="title-editor">
            <input
              data-testid="mdtodo-edit-title"
              :value="editTitle"
              :disabled="mutationLoading || mutationDisabled"
              aria-label="任务标题"
              @input="emit('update:editTitle', ($event.target as HTMLInputElement).value)"
              @keydown.enter="emit('saveTaskBasics')"
              @keydown.esc="emit('cancelTitleEdit')"
            />
            <button
              class="icon-button"
              type="button"
              data-testid="mdtodo-edit-save"
              title="保存标题"
              aria-label="保存标题"
              :disabled="mutationLoading || mutationDisabled"
              @click="emit('saveTaskBasics')"
            >
              <Save :size="15" aria-hidden="true" />
            </button>
            <button
              class="icon-button"
              type="button"
              title="取消标题编辑"
              aria-label="取消标题编辑"
              :disabled="mutationLoading"
              @click="emit('cancelTitleEdit')"
            >
              <X :size="15" aria-hidden="true" />
            </button>
          </div>
          <button
            v-else
            class="title-button"
            type="button"
            data-testid="mdtodo-title-read"
            :disabled="mutationDisabled"
            title="双击或按 Enter/F2 编辑标题"
            @dblclick="emit('beginTitleEdit')"
            @keydown="titleKeydown"
          >
            {{ task.title || "未命名任务" }}
          </button>
        </div>
        <label class="status-editor">
          <span>状态</span>
          <select
            data-testid="mdtodo-edit-status"
            :value="editStatus"
            :disabled="mutationLoading || mutationDisabled"
            @change="updateStatus"
          >
            <option value="open">待办</option>
            <option value="in_progress">进行中</option>
            <option value="completed">完成</option>
          </select>
        </label>
      </header>

      <div
        v-if="mutationMessage || mutationError || detailError"
        class="document-notice"
        data-testid="mdtodo-task-notice"
        :data-error="Boolean(mutationError || detailError)"
        role="status"
      >
        {{ mutationError || detailError || mutationMessage }}
      </div>
      <ApiErrorDiagnostic
        v-if="launchError || launchApiError || launchDiagnostic"
        title="Workbench 启动失败"
        :error="launchError"
        :api-error="launchApiError"
        :diagnostic="launchDiagnostic"
        compact
      />

      <RefreshBoundary
        class="document-boundary"
        :loading="detailLoading"
        mode="persistent"
        :has-content="Boolean(task)"
        label="读取 Markdown 正文"
      >
        <textarea
          v-if="editingBody"
          class="document-editor"
          data-testid="mdtodo-body-editor"
          :value="editBody"
          :disabled="mutationLoading || mutationDisabled"
          aria-label="Markdown 正文编辑器"
          @input="emit('update:editBody', ($event.target as HTMLTextAreaElement).value)"
          @keydown.esc="emit('cancelBodyEdit')"
        />
        <div
          v-else
          class="markdown-document"
          data-testid="mdtodo-body-read"
          title="双击编辑 Markdown 正文"
          @dblclick="!mutationDisabled && emit('beginBodyEdit')"
        >
          <ContentViewer
            :content="detail?.body || task.bodyPreview || ''"
            mode="markdown"
            title="任务正文"
            :filename="`${task.taskId || task.rxxId || 'task'}.md`"
            :line-numbers="false"
          />
        </div>
      </RefreshBoundary>

      <footer class="document-footer">
        <div class="edit-actions">
          <template v-if="editingBody">
            <button
              class="btn btn-primary"
              type="button"
              data-testid="mdtodo-body-save"
              :disabled="mutationLoading || mutationDisabled"
              @click="emit('saveTaskBody')"
            >
              <Save :size="15" aria-hidden="true" />保存正文
            </button>
            <button class="btn" type="button" @click="emit('cancelBodyEdit')">
              取消
            </button>
          </template>
          <button
            v-else
            class="btn"
            type="button"
            data-testid="mdtodo-body-edit"
            :disabled="mutationDisabled"
            @click="emit('beginBodyEdit')"
          >
            <Pencil :size="15" aria-hidden="true" />编辑正文
          </button>
          <button
            class="btn btn-danger"
            type="button"
            data-testid="mdtodo-delete-task"
            :disabled="mutationLoading || mutationDisabled"
            @click="emit('deleteTask')"
          >
            <Trash2 :size="15" aria-hidden="true" />
            {{ deleteConfirm ? "确认删除" : "删除" }}
          </button>
          <button
            v-if="deleteConfirm"
            class="btn"
            type="button"
            @click="emit('cancelDelete')"
          >
            取消删除
          </button>
        </div>

        <div class="report-links" aria-label="任务报告">
          <button
            v-for="link in links"
            :key="link.linkId"
            class="report-link"
            type="button"
            data-testid="mdtodo-report-link"
            :disabled="link.availability === 'projected-link-unavailable'"
            :title="link.message || link.relativePath || undefined"
            @click="emit('openReport', link)"
          >
            <FileText :size="14" aria-hidden="true" />
            {{ link.label || link.relativePath || "报告" }}
          </button>
          <span v-if="links.length === 0" class="no-reports">暂无报告链接</span>
        </div>

        <div class="launch-controls">
          <select
            id="mdtodo-provider-profile"
            data-testid="mdtodo-provider-profile"
            :value="providerProfile"
            aria-label="模型通道"
            @change="emit('update:providerProfile', ($event.target as HTMLSelectElement).value as ProviderProfile)"
          >
            <option
              v-for="option in providerOptions"
              :key="option.value"
              :value="option.value"
              :disabled="option.configured === false"
            >
              {{ option.label }}
            </option>
          </select>
          <button
            class="btn btn-primary"
            type="button"
            data-testid="mdtodo-launch-workbench"
            :disabled="!launchEnabled || launchLoading"
            :title="launchBlocker || undefined"
            @click="emit('launchWorkbench')"
          >
            <ExternalLink :size="15" aria-hidden="true" />
            {{ launchLoading ? "启动中…" : "Workbench" }}
          </button>
          <small v-if="launchBlocker" class="launch-blocker">{{ launchBlocker }}</small>
        </div>
      </footer>
    </template>

    <EmptyState
      v-else
      title="选择任务"
      description="从左侧任务树选择一个 Rxx，正文、报告和执行入口会在同一深链上下文中打开。"
    />
  </SectionFrame>
</template>

<style scoped>
.document-workspace {
  min-width: 0;
  min-height: 0;
  height: 100%;
  border: 0;
  border-radius: 0;
  background: var(--console-surface, #fff);
}
.document-workspace :deep(.console-section-body) {
  display: grid;
  min-height: 0;
  grid-template-rows: auto auto auto minmax(0, 1fr) auto;
}
.authority-warning,
.authority-ready {
  font: 750 10px ui-monospace, monospace;
  text-transform: uppercase;
}
.authority-warning {
  color: var(--console-danger, #9b4a34);
}
.authority-ready {
  color: var(--console-success, #287047);
}
.document-command-strip {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--console-border, #c7d3d9);
  background: var(--console-surface-subtle, #f4f7f8);
  padding: 8px 10px;
}
.title-region,
.title-editor,
.status-editor,
.edit-actions,
.launch-controls {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 7px;
}
.title-button {
  overflow: hidden;
  border: 0;
  background: transparent;
  padding: 0;
  color: var(--console-text, #152a33);
  font-size: 15px;
  font-weight: 780;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.title-editor input {
  min-width: 260px;
  height: 30px;
  border: 1px solid var(--console-border-strong, #8fa7b2);
  background: var(--console-surface, #fff);
  padding: 0 8px;
}
.status-editor span {
  color: var(--console-text-muted, #607680);
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
}
.status-editor select,
.launch-controls select {
  height: 30px;
  border: 1px solid var(--console-border-strong, #9fb2bb);
  background: var(--console-surface, #fff);
}
.document-notice {
  border-bottom: 1px solid #b7d8c2;
  background: #edf8f1;
  padding: 7px 12px;
  color: #276342;
  font-size: 12px;
}
.document-notice[data-error="true"] {
  border-color: #e3b5ad;
  background: #fff1ef;
  color: #963e31;
}
.document-boundary,
.markdown-document,
.document-editor {
  min-width: 0;
  min-height: 0;
  height: 100%;
}
.document-boundary {
  overflow: hidden;
}
.markdown-document {
  overflow: auto;
  padding: 10px;
}
.markdown-document :deep(.content-viewer) {
  min-height: 100%;
}
.document-editor {
  box-sizing: border-box;
  width: 100%;
  resize: none;
  border: 0;
  background: #f8fbfc;
  padding: 18px 22px;
  color: var(--console-text, #172b34);
  font: 13px/1.65 ui-monospace, monospace;
}
.document-footer {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  border-top: 1px solid var(--console-border, #c7d3d9);
  background: var(--console-surface-subtle, #f2f6f7);
  padding: 7px 9px;
}
.document-footer button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.report-links {
  display: flex;
  min-width: 0;
  gap: 6px;
  overflow: auto;
}
.report-link {
  display: inline-flex;
  min-height: 29px;
  flex: 0 0 auto;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--console-border-strong, #9fb2bb);
  background: var(--console-surface, #fff);
  color: var(--console-accent, #1f718c);
  font-size: 11px;
  font-weight: 700;
}
.no-reports,
.launch-blocker {
  color: var(--console-text-muted, #607680);
  font-size: 10px;
}
.launch-blocker {
  max-width: 200px;
  color: var(--console-danger, #98503c);
}
@media (max-width: 960px) {
  .document-footer {
    grid-template-columns: 1fr;
  }
  .launch-controls {
    flex-wrap: wrap;
  }
}
@media (max-width: 540px) {
  .document-command-strip {
    grid-template-columns: 1fr;
  }
  .title-editor input {
    min-width: 0;
    width: 100%;
  }
  .document-editor {
    padding: 14px;
  }
}
</style>
