'use client';

import React from 'react';
import {
  BarChart3,
  CheckCircle2,
  ChevronDown,
  Clock3,
  Database,
  Download,
  Eye,
  FileImage,
  FileJson,
  FileText,
  Globe2,
  Grid2X2,
  ListFilter,
  Network,
  PackageOpen,
  RefreshCw,
  ShieldCheck,
  Table2,
  UserRound,
} from 'lucide-react';

import type { TaskFeedbackType } from '@/components/task-detail/TaskAcceptanceCard';
import type { TaskResultAcceptance } from '@/components/task-detail/TaskTimelineCard';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { formatTaskRuntimeDuration, formatTaskRuntimeTime } from '@/components/task-runtime/TaskRuntimeShared';
import { pickAppText } from '@/lib/i18n/core';
import { useAppI18n } from '@/lib/i18n/provider';
import {
  buildTaskUiModel,
  taskUiStatusClass,
  taskUiStatusLabel,
  type TaskUiAgentNode,
  type TaskUiArtifact,
  type TaskUiAttempt,
  type TaskUiModel,
  type TaskUiStatus,
  type TaskUiStep,
} from '@/lib/task-ui-model';
import { containedLongTextClass, containedPreservedLongTextClass } from '@/lib/text-wrapping';
import type { BackendTask, SessionProcessProjection, TaskTimelineCard } from '@/types';

type Props = {
  task: BackendTask;
  process: SessionProcessProjection;
  cards: TaskTimelineCard[];
  isLive: boolean;
  resultAcceptance?: TaskResultAcceptance;
  reviewTargetId?: string;
};

function StatusBadge({ status, compact = false }: { status: TaskUiStatus; compact?: boolean }) {
  const { locale } = useAppI18n();
  return (
    <Badge
      variant="outline"
      className={`${compact ? 'h-6 px-2 text-[11px]' : 'h-7 px-3 text-xs'} rounded-full font-medium ${taskUiStatusClass(status)}`}
    >
      {taskUiStatusLabel(status, locale)}
    </Badge>
  );
}

function Section({
  title,
  children,
  action,
  className = '',
}: {
  title: string;
  children: React.ReactNode;
  action?: React.ReactNode;
  className?: string;
}) {
  return (
    <section className={`min-w-0 rounded-lg border border-[#E6E1DE] bg-white ${className}`}>
      <div className="flex min-h-[50px] items-center justify-between gap-3 px-5 py-2.5">
        <h2 className="text-base font-semibold text-[#1D1715]">{title}</h2>
        {action}
      </div>
      {children}
    </section>
  );
}

function EmptyState({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex min-h-[120px] flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-[#DED8D4] bg-[#FBFAF9] px-4 py-8 text-center text-sm text-muted-foreground">
      <PackageOpen className="h-5 w-5 text-[#8D8782]" />
      {children}
    </div>
  );
}

function iconForStep(kind: TaskUiStep['kind']) {
  if (kind === 'skill') return Grid2X2;
  if (kind === 'tool') return Clock3;
  if (kind === 'agent') return Network;
  if (kind === 'artifact') return FileText;
  if (kind === 'result') return BarChart3;
  return FileText;
}

function statusDotClass(status: TaskUiStatus) {
  if (status === 'done') return 'bg-[#22733A]';
  if (status === 'running') return 'bg-[#C47B00]';
  if (status === 'error') return 'bg-[#9D3D2F]';
  if (status === 'cancelled') return 'bg-[#756A64]';
  return 'bg-[#8D8782]';
}

function ExecutionFlow({ model }: { model: TaskUiModel }) {
  const { locale } = useAppI18n();
  const steps = model.steps.slice(0, 6);
  const columnClass = steps.length >= 6 ? 'grid-cols-6' : steps.length >= 4 ? 'grid-cols-4' : steps.length >= 2 ? 'grid-cols-2' : 'grid-cols-1';

  return (
    <Section
      title="任务执行流程"
      action={
        <Button variant="outline" size="sm" className="h-9 rounded-lg border-[#E6E1DE] bg-white text-xs">
          查看详情
        </Button>
      }
    >
      <div className="px-5 pb-4">
        <div className={`relative grid gap-5 ${columnClass}`}>
          {steps.length > 1 ? <div className="absolute left-8 right-8 top-[17px] h-px bg-[#CFC8C3]" /> : null}
          {steps.map((step) => {
            const Icon = iconForStep(step.kind);
            return (
              <div key={step.id} className="relative min-w-0">
                <div className="relative z-10 flex h-10 items-center">
                  <span className={`flex h-5 w-5 items-center justify-center rounded-full ${statusDotClass(step.status)}`}>
                    {step.status === 'done' ? <CheckCircle2 className="h-3.5 w-3.5 text-white" /> : <span className="h-1.5 w-1.5 rounded-full bg-white" />}
                  </span>
                  <span className="ml-5 flex h-10 w-10 items-center justify-center rounded-full border border-[#D8D2CE] bg-[#F8F6F4]">
                    <Icon className="h-5 w-5 text-[#1D1715]" />
                  </span>
                </div>
                <h3 className={`text-sm font-semibold text-[#1D1715] ${containedLongTextClass}`}>{step.title}</h3>
                <div className="mt-1 flex flex-wrap items-center gap-2">
                  {step.createdAt ? <span className="text-xs text-muted-foreground">{formatTaskRuntimeTime(step.createdAt, locale)}</span> : null}
                  <StatusBadge status={step.status} compact />
                </div>
                {step.summary ? (
                  <p className={`mt-1 line-clamp-4 text-xs leading-[17px] text-[#4F4642] ${containedPreservedLongTextClass}`}>{step.summary}</p>
                ) : null}
              </div>
            );
          })}
        </div>
      </div>
    </Section>
  );
}

function progressColor(status: TaskUiStatus) {
  if (status === 'done') return '#137333';
  if (status === 'running') return '#D48500';
  if (status === 'error') return '#9D3D2F';
  if (status === 'cancelled') return '#756A64';
  return '#E3DFDC';
}

function AgentCard({ agent, root = false }: { agent: TaskUiAgentNode; root?: boolean }) {
  return (
    <div className={`relative rounded-lg border border-[#E1DCD8] bg-white px-3 py-3 ${root ? 'h-[68px] w-60 shadow-[0_2px_8px_rgba(31,24,20,0.05)]' : 'h-[90px] w-[150px]'}`}>
      <div className="flex items-center justify-between gap-2">
        <div className="flex min-w-0 items-center gap-2">
          <UserRound className="h-4 w-4 shrink-0 text-[#1D1715]" />
          <span className="min-w-0 truncate text-[13px] font-semibold leading-5">{agent.title || agent.name}</span>
        </div>
        <div className={root ? '' : 'absolute right-3 top-8'}>
          <StatusBadge status={agent.status} compact />
        </div>
      </div>
      <div className={root ? 'mt-3 h-1.5 rounded-full bg-[#ECE8E5]' : 'mt-8 h-1.5 rounded-full bg-[#ECE8E5]'}>
        <div className="h-full rounded-full" style={{ width: `${agent.progress}%`, backgroundColor: progressColor(agent.status) }} />
      </div>
      <div className="mt-2 text-right text-xs text-[#4F4642]">{agent.progress}%</div>
    </div>
  );
}

function AgentDAG({ model }: { model: TaskUiModel }) {
  const { locale } = useAppI18n();
  const roots = model.agentTree;
  const root = roots.find((node) => node.children.length > 0) ?? roots[0];
  const children = root?.children.length ? root.children : roots.filter((node) => node.runId !== root?.runId);
  const visibleChildren = children.slice(0, 5);

  if (!model.team.hasTeam) {
    return null;
  }

  return (
    <Section
      title={pickAppText(locale, 'Agent Team 执行图', 'Agent Team execution graph')}
      action={
        <div className="flex flex-wrap items-center gap-2">
          <Badge variant="outline" className="rounded-full border-[#E1DCD8] bg-[#FBFAF9] text-[11px]">
            {model.team.outcome}
          </Badge>
          <StatusBadge status={model.team.status} compact />
        </div>
      }
    >
      <div className="px-5 pb-5">
        {roots.length === 0 ? (
          <EmptyState>{pickAppText(locale, '暂无 Agent Team 数据', 'No Agent Team data yet')}</EmptyState>
        ) : (
          <div className="relative min-h-[196px]">
            {visibleChildren.length > 0 ? (
              <>
                <div className="absolute left-1/2 top-[70px] h-10 w-px -translate-x-1/2 bg-[#1D1715]" />
                <div className="absolute left-[9%] right-[9%] top-[110px] h-px bg-[#1D1715]" />
                {visibleChildren.map((child, index) => (
                  <div
                    key={child.runId}
                    className="absolute top-[110px] h-7 w-px bg-[#1D1715]"
                    style={{ left: `${9 + index * (82 / Math.max(visibleChildren.length - 1, 1))}%` }}
                  />
                ))}
              </>
            ) : null}
            <div className="flex justify-center">
              <AgentCard agent={root} root />
            </div>
            {visibleChildren.length > 0 ? (
              <div className="absolute bottom-0 left-0 right-0 flex items-end justify-between gap-4 px-6">
                {visibleChildren.map((agent) => (
                  <AgentCard key={agent.runId} agent={agent} />
                ))}
              </div>
            ) : null}
          </div>
        )}
      </div>
    </Section>
  );
}

function RunPath({
  model,
  selectedAttemptId,
  onSelectAttempt,
}: {
  model: TaskUiModel;
  selectedAttemptId: string | null;
  onSelectAttempt: (attemptId: string) => void;
}) {
  const { locale } = useAppI18n();
  const [expandedIds, setExpandedIds] = React.useState<Set<string>>(() => new Set());
  const attempts = model.attempts.filter((attempt) => attempt.runs.length > 0 || attempt.tools.length > 0 || attempt.result);

  if (attempts.length === 0) return null;

  return (
    <Section
      title={pickAppText(locale, '运行路径与结果版本', 'Run path and result versions')}
      action={
        <Badge variant="outline" className="h-7 rounded-full border-[#E1DCD8] bg-[#FBFAF9] text-[11px]">
          {attempts.length} runs
        </Badge>
      }
    >
      <div className="space-y-3 border-t border-[#ECE8E5] p-4">
        {attempts.map((attempt) => (
          <div
            key={attempt.id}
            onClick={() => onSelectAttempt(attempt.id)}
            onKeyDown={(event) => {
              if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                onSelectAttempt(attempt.id);
              }
            }}
            role="group"
            tabIndex={0}
            aria-label={pickAppText(locale, `选择${attempt.title}`, `Select ${attempt.title}`)}
            className={`rounded-lg border p-4 transition-colors ${
              selectedAttemptId === attempt.id
                ? 'border-[#1D1715] bg-white shadow-[0_6px_18px_rgba(31,24,20,0.06)]'
                : 'border-[#E1DCD8] bg-[#FBFAF9]'
            } cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#1D1715] focus-visible:ring-offset-2`}
          >
            <div className="flex w-full min-w-0 items-center justify-between gap-3 text-left">
              <div className="min-w-0">
                <div className="flex min-w-0 flex-wrap items-center gap-2">
                  <h3 className="text-sm font-semibold text-[#1D1715]">{attempt.title}</h3>
                  <StatusBadge status={attempt.status} compact />
                </div>
                <div className="mt-1 text-xs text-muted-foreground">
                  {formatTaskRuntimeTime(attempt.startedAt, locale)}
                  {attempt.finishedAt ? ` · ${formatAttemptDuration(attempt.startedAt, attempt.finishedAt, locale)}` : ''}
                </div>
              </div>
              <div className="shrink-0 text-xs text-muted-foreground">
                {attempt.tools.length} tools
              </div>
            </div>

            {attempt.runs.length > 0 ? (
              <div className="mt-3 flex min-w-0 flex-wrap items-center gap-2">
                {attempt.runs.map((run, index) => (
                  <React.Fragment key={run.runId}>
                    {index > 0 ? <span className="text-xs text-[#B8AEA8]">→</span> : null}
                    <span className="inline-flex max-w-[220px] items-center gap-1.5 rounded-full border border-[#E1DCD8] bg-white px-2.5 py-1 text-xs text-[#4F4642]">
                      <span className={`h-1.5 w-1.5 rounded-full ${run.status === 'done' ? 'bg-[#22733A]' : run.status === 'error' ? 'bg-[#9D3D2F]' : run.status === 'running' ? 'bg-[#C47B00]' : 'bg-[#8D8782]'}`} />
                      <span className="truncate">{run.actorName || run.title}</span>
                    </span>
                  </React.Fragment>
                ))}
              </div>
            ) : null}

            <button
              type="button"
              onClick={() => {
                onSelectAttempt(attempt.id);
                setExpandedIds((current) => {
                  const next = new Set(current);
                  if (next.has(attempt.id)) next.delete(attempt.id);
                  else next.add(attempt.id);
                  return next;
                });
              }}
              className="mt-3 flex h-8 items-center gap-1 rounded-md px-2 text-xs font-medium text-[#615854] hover:bg-[#F4F1EF]"
              aria-expanded={expandedIds.has(attempt.id)}
            >
              {expandedIds.has(attempt.id)
                ? pickAppText(locale, '收起结果', 'Collapse result')
                : pickAppText(locale, '展开结果', 'Expand result')}
              <ChevronDown className={`h-3.5 w-3.5 transition-transform ${expandedIds.has(attempt.id) ? 'rotate-180' : ''}`} />
            </button>

            {attempt.result && expandedIds.has(attempt.id) ? (
              <div className="mt-3 rounded-md border border-[#E6E1DE] bg-white p-3">
                <div className="mb-1 flex items-center justify-between gap-2">
                  <span className="text-xs font-medium text-[#615854]">
                    {pickAppText(locale, '本次结果', 'Attempt result')}
                  </span>
                  <StatusBadge status={attempt.result.status} compact />
                </div>
                <p className={`line-clamp-3 text-xs leading-5 text-[#4F4642] ${containedPreservedLongTextClass}`}>
                  {attempt.result.summary || attempt.result.title}
                </p>
              </div>
            ) : null}
          </div>
        ))}
      </div>
    </Section>
  );
}

function formatAttemptDuration(startedAt: string, finishedAt: string, locale: string): string {
  const startMs = new Date(startedAt).getTime();
  const finishMs = new Date(finishedAt).getTime();
  if (Number.isNaN(startMs) || Number.isNaN(finishMs) || finishMs < startMs) return '-';
  return formatTaskRuntimeDuration(finishMs - startMs, locale);
}

function toolsForAttempt(model: TaskUiModel, selectedAttemptId: string | null): TaskUiAttempt {
  return (
    model.attempts.find((attempt) => attempt.id === selectedAttemptId) ??
    model.attempts.at(-1) ??
    {
      id: 'all',
      index: 1,
      title: 'Agent',
      status: 'waiting',
      startedAt: '',
      runs: [],
      tools: model.tools,
    }
  );
}

function ToolCalls({ model, selectedAttemptId }: { model: TaskUiModel; selectedAttemptId: string | null }) {
  const { locale } = useAppI18n();
  const selectedAttempt = toolsForAttempt(model, selectedAttemptId);
  const agents = Array.from(new Set(selectedAttempt.tools.map((tool) => tool.actorName || 'Agent')));
  const [selectedAgent, setSelectedAgent] = React.useState<string | null>(null);
  const activeAgent = selectedAgent && agents.includes(selectedAgent) ? selectedAgent : agents[0] ?? 'Agent';
  const visibleTools = selectedAttempt.tools.filter((tool) => (tool.actorName || 'Agent') === activeAgent);

  return (
    <Section
      title={pickAppText(locale, '运行摘要', 'Run summary')}
      action={
        <div className="flex gap-2">
          <Badge variant="outline" className="h-7 rounded-full border-[#E1DCD8] bg-[#FBFAF9] text-[11px]">
            {selectedAttempt.title}
          </Badge>
        </div>
      }
    >
      {selectedAttempt.tools.length === 0 ? (
        <div className="border-t border-[#ECE8E5] p-5">
          <EmptyState>{pickAppText(locale, '暂无工具调用', 'No tool calls yet')}</EmptyState>
        </div>
      ) : (
        <div className="grid grid-cols-[170px_minmax(0,1fr)] border-t border-[#ECE8E5]">
          <aside className="border-r border-[#ECE8E5] bg-[#FBFAF9] p-4">
            {agents.map((name) => {
              const count = selectedAttempt.tools.filter((tool) => (tool.actorName || 'Agent') === name).length;
              return (
              <button
                key={name}
                type="button"
                onClick={() => setSelectedAgent(name)}
                className={`flex min-h-10 w-full items-center gap-2 rounded-md px-2 py-1 text-left text-sm ${
                  activeAgent === name ? 'bg-white text-[#1D1715] ring-1 ring-[#E1DCD8]' : 'text-[#615854] hover:bg-white'
                }`}
              >
                <Network className="h-3.5 w-3.5 text-[#615854]" />
                <span className="min-w-0">
                  <span className="block truncate">{model.team.hasTeam ? name : 'Agent'}</span>
                  <span className="block text-xs text-muted-foreground">{count} calls</span>
                </span>
              </button>
              );
            })}
          </aside>
          <div className="min-w-0 overflow-hidden">
            <div className="grid grid-cols-[150px_minmax(0,1fr)_96px_96px] border-b border-[#ECE8E5] px-4 py-3 text-xs font-medium text-[#615854]">
              <span>工具名称</span>
              <span>摘要</span>
              <span>状态</span>
              <span>运行时间</span>
            </div>
            {visibleTools.map((tool) => (
              <div key={tool.id} className="grid min-h-[56px] grid-cols-[150px_minmax(0,1fr)_96px_96px] items-center gap-3 border-b border-[#F0ECE9] px-4 text-sm last:border-b-0">
                <span className="truncate font-medium text-[#1D1715]">{tool.toolName}</span>
                <span className={`text-[#4F4642] ${containedLongTextClass}`}>
                  {tool.summary}
                </span>
                <StatusBadge status={tool.status} compact />
                <span className="text-[#4F4642]">{formatToolDuration(tool, locale)}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </Section>
  );
}

function formatToolDuration(tool: TaskUiModel['tools'][number], locale: string): string {
  if (typeof tool.durationMs === 'number') {
    return formatTaskRuntimeDuration(tool.durationMs, locale);
  }
  if (tool.status === 'running' && tool.createdAt) {
    const startMs = new Date(tool.createdAt).getTime();
    if (!Number.isNaN(startMs)) {
      return formatTaskRuntimeDuration(Date.now() - startMs, locale);
    }
  }
  return '-';
}

function iconForArtifact(artifact: TaskUiArtifact) {
  if (artifact.type === 'json') return FileJson;
  if (artifact.type === 'image') return FileImage;
  return FileText;
}

function WorkspaceFiles({ model }: { model: TaskUiModel }) {
  const { locale } = useAppI18n();

  return (
    <Section
      title="Workspace 文件"
      action={
        <div className="flex gap-2">
          <Button variant="ghost" size="icon" className="h-9 w-9 rounded-lg" aria-label={pickAppText(locale, '刷新', 'Refresh')}>
            <RefreshCw className="h-4 w-4" />
          </Button>
          <Button variant="outline" size="sm" className="h-9 rounded-lg border-[#E6E1DE] bg-white text-xs">
            打开 Workspace
          </Button>
        </div>
      }
    >
      <div className="border-t border-[#ECE8E5]">
        <div className="flex h-12 items-end gap-8 px-5 text-sm">
          <button className="h-10 border-b-2 border-[#1D1715] font-medium text-[#1D1715]">参考文件</button>
          <button className="h-10 text-[#615854]">输出文件</button>
          <button className="h-10 text-[#615854]">日志</button>
        </div>
        {model.artifacts.length === 0 ? (
          <div className="p-5">
            <EmptyState>{pickAppText(locale, '暂无 Workspace 文件', 'No workspace files yet')}</EmptyState>
          </div>
        ) : (
          <>
            <div className="grid grid-cols-[minmax(0,1.4fr)_70px_78px_82px_96px] border-y border-[#ECE8E5] px-5 py-3 text-xs font-medium text-[#615854]">
              <span>文件名</span>
              <span>类型</span>
              <span>大小</span>
              <span>状态</span>
              <span>操作</span>
            </div>
            <div className="px-5 py-2">
              {model.artifacts.slice(0, 6).map((artifact) => {
                const Icon = iconForArtifact(artifact);
                return (
                  <div key={artifact.id} className="grid min-h-[48px] grid-cols-[minmax(0,1.4fr)_70px_78px_82px_96px] items-center text-sm">
                    <div className="flex min-w-0 items-center gap-3">
                      <span className="flex h-7 w-7 items-center justify-center rounded border border-[#E1DCD8] bg-[#F8F6F4]">
                        <Icon className="h-4 w-4 text-[#3F7D54]" />
                      </span>
                      <span className={`font-medium ${containedLongTextClass}`}>{artifact.title}</span>
                    </div>
                    <span className="text-[#4F4642]">{artifact.type.toUpperCase()}</span>
                    <span className="text-[#4F4642]">{artifact.sizeLabel || '-'}</span>
                    <StatusBadge status={artifact.status} compact />
                    <div className="flex gap-2">
                      <Button variant="outline" size="sm" className="h-8 rounded-lg border-[#E6E1DE] bg-white px-2 text-xs" disabled={!artifact.url && !artifact.fileId}>
                        <Eye className="mr-1 h-3.5 w-3.5" />
                        预览
                      </Button>
                      <Button variant="outline" size="icon" className="h-8 w-8 rounded-lg border-[#E6E1DE] bg-white" disabled={!artifact.url && !artifact.fileId}>
                        <Download className="h-3.5 w-3.5" />
                      </Button>
                    </div>
                  </div>
                );
              })}
              {model.artifacts.length > 6 ? (
                <button className="mt-1 h-9 text-sm font-medium text-[#1F6FEB]">
                  {pickAppText(locale, `查看全部 (${model.artifacts.length})`, `View all (${model.artifacts.length})`)}
                </button>
              ) : null}
            </div>
          </>
        )}
      </div>
    </Section>
  );
}

function ResultPanel({
  model,
  resultAcceptance,
  reviewTargetId,
}: {
  model: TaskUiModel;
  resultAcceptance?: TaskResultAcceptance;
  reviewTargetId?: string;
}) {
  const { locale } = useAppI18n();
  const [busyAction, setBusyAction] = React.useState<TaskFeedbackType | null>(null);
  const submit = async (type: TaskFeedbackType) => {
    if (!resultAcceptance || busyAction) return;
    setBusyAction(type);
    try {
      await resultAcceptance.onSubmit(type);
    } finally {
      setBusyAction(null);
    }
  };

  return (
    <Section title="本轮结果（摘要）" action={<StatusBadge status={model.result.status} compact />}>
      <div id={reviewTargetId} className="space-y-4 border-t border-[#ECE8E5] p-4 scroll-mt-44">
        {model.result.summary ? (
          <div className="rounded-lg border border-[#E1DCD8] bg-[#FBFAF9] p-4">
            <p className="max-h-[240px] overflow-auto pr-2 text-sm leading-6 text-[#1D1715]">{model.result.summary}</p>
            {model.result.bullets.length > 0 ? (
              <div className="mt-5 space-y-4 text-sm text-[#1D1715]">
                {model.result.bullets.map((item, index) => {
                  const Icon = [Globe2, Table2, BarChart3, ShieldCheck][index % 4];
                  return (
                    <div key={`${item}:${index}`} className="flex gap-3">
                      <Icon className="h-5 w-5 shrink-0" />
                      <span>{item}</span>
                    </div>
                  );
                })}
              </div>
            ) : null}
          </div>
        ) : (
          <EmptyState>{pickAppText(locale, '暂无本轮结果', 'No result for this run yet')}</EmptyState>
        )}
        <div className="flex flex-wrap gap-3">
          <Button className="h-11 rounded-lg px-5" disabled={!resultAcceptance || Boolean(busyAction)} onClick={() => void submit('accept')}>
            <CheckCircle2 className="mr-2 h-4 w-4" />
            接受结果
          </Button>
          <Button variant="outline" className="h-11 rounded-lg border-[#E6E1DE] bg-white px-5" disabled={!resultAcceptance || Boolean(busyAction)} onClick={() => void submit('revise')}>
            <ListFilter className="mr-2 h-4 w-4" />
            需要修改
          </Button>
          <Button variant="outline" className="h-11 rounded-lg border-[#E6E1DE] bg-white px-5" disabled={!resultAcceptance || Boolean(busyAction)} onClick={() => void submit('abandon')}>
            <Database className="mr-2 h-4 w-4" />
            放弃
          </Button>
        </div>
      </div>
    </Section>
  );
}

export function TaskExecutionWorkspace({ task, process, cards, resultAcceptance, reviewTargetId }: Props) {
  const { locale } = useAppI18n();
  const model = React.useMemo(
    () => buildTaskUiModel({ task, process, cards, locale }),
    [cards, locale, process, task],
  );
  const latestAttemptId = model.attempts.at(-1)?.id ?? null;
  const [selectedAttemptState, setSelectedAttemptState] = React.useState<string | null>(latestAttemptId);
  const selectedAttemptId = model.attempts.some((attempt) => attempt.id === selectedAttemptState)
    ? selectedAttemptState
    : latestAttemptId;

  return (
    <div className="grid min-w-0 grid-cols-[minmax(0,1fr)_514px] gap-5">
      <div className="min-w-0 space-y-3">
        <ExecutionFlow model={model} />
        <AgentDAG model={model} />
        <RunPath model={model} selectedAttemptId={selectedAttemptId} onSelectAttempt={setSelectedAttemptState} />
        <ToolCalls model={model} selectedAttemptId={selectedAttemptId} />
      </div>
      <div className="min-w-0 space-y-3">
        <WorkspaceFiles model={model} />
        <ResultPanel model={model} resultAcceptance={resultAcceptance} reviewTargetId={reviewTargetId} />
      </div>
    </div>
  );
}
