"use client";

import {
  ArrowRightIcon,
  BuildingsIcon,
  CheckIcon,
  CircleNotchIcon,
  CubeIcon,
  DownloadSimpleIcon,
  GearSixIcon,
  ImageIcon,
  MagicWandIcon,
  PaperPlaneTiltIcon,
  PencilSimpleIcon,
  PlusIcon,
  SparkleIcon,
  UploadSimpleIcon,
  WarningCircleIcon,
} from "@phosphor-icons/react";
import { ChangeEvent, FormEvent, useEffect, useMemo, useRef, useState } from "react";

import { SettingsCenter } from "@/components/settings-center";
import type { DesignBrief, ProjectSnapshot, RenderAsset, WorkflowStageId } from "@/types/workflow";
import type { SettingsReadiness } from "@/types/settings";

const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8000";

const EMPTY_BRIEF: DesignBrief = {
  residents: "",
  lifestyle: [],
  focus_rooms: [],
  preferred_styles: [],
  preferred_colors: [],
  disliked_elements: [],
  must_keep: [],
  budget_level: "适中",
  additional_notes: "",
  completed: false,
};

const STAGES: Array<{ ids: Array<WorkflowStageId | "failed">; label: string; detail: string }> = [
  { ids: ["uploaded", "region_selection"], label: "导入图纸", detail: "找到正确户型" },
  { ids: ["plan_review", "blockout"], label: "理解空间", detail: "房间、动线、采光" },
  { ids: ["style_brief"], label: "说清需求", detail: "生活方式与偏好" },
  { ids: ["direction_selection"], label: "选择方向", detail: "三套 Style DNA" },
  { ids: ["render_review"], label: "生成效果", detail: "真实模型出图" },
  { ids: ["editing"], label: "多轮修改", detail: "保留版本继续改" },
  { ids: ["completed"], label: "完成方案", detail: "查看与导出" },
];

const LIFESTYLE_OPTIONS = ["经常下厨", "在家办公", "亲子活动", "朋友聚会", "重视收纳", "养宠物"];
const STYLE_OPTIONS = ["现代简约", "原木自然", "中古现代", "侘寂", "现代法式", "轻工业"];
const COLOR_OPTIONS = ["黑白灰", "自然木色", "低饱和彩色", "冷色调", "暖色调", "深色氛围"];

function stageIndex(stage?: WorkflowStageId | "failed") {
  if (!stage) return 0;
  const index = STAGES.findIndex((item) => item.ids.includes(stage));
  return index < 0 ? 0 : index;
}

function PlanPreview({ project, selectable, onSelect }: {
  project: ProjectSnapshot;
  selectable?: boolean;
  onSelect?: (id: string) => void;
}) {
  return (
    <div className="product-plan-frame">
      {/* eslint-disable-next-line @next/next/no-img-element -- local authenticated project preview. */}
      <img src={`${API_BASE}/v1/projects/${project.project_id}/preview`} alt={`${project.name} 户型图`} />
      {selectable ? (
        <div className="product-region-layer">
          {project.plan.regions.map((region, index) => {
            const [x0, y0, x1, y1] = region.bounds;
            return (
              <button
                key={region.id}
                type="button"
                className={region.recommended ? "recommended" : ""}
                style={{ left: `${x0 * 100}%`, top: `${y0 * 100}%`, width: `${(x1 - x0) * 100}%`, height: `${(y1 - y0) * 100}%` }}
                onClick={() => onSelect?.(region.id)}
              >
                <strong>候选 {index + 1}</strong>
                <span>{Math.round(region.confidence * 100)}%{region.recommended ? "，建议" : ""}</span>
              </button>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}

function ChoiceGroup({ label, options, values, onChange }: {
  label: string;
  options: string[];
  values: string[];
  onChange: (next: string[]) => void;
}) {
  return (
    <fieldset className="choice-group">
      <legend>{label}</legend>
      <div>
        {options.map((option) => (
          <button
            key={option}
            type="button"
            className={values.includes(option) ? "selected" : ""}
            onClick={() => onChange(values.includes(option) ? values.filter((item) => item !== option) : [...values, option])}
          >
            {values.includes(option) ? <CheckIcon size={13} weight="bold" /> : null}{option}
          </button>
        ))}
      </div>
    </fieldset>
  );
}

export function WorkflowStudio() {
  const [project, setProject] = useState<ProjectSnapshot | null>(null);
  const [readiness, setReadiness] = useState<SettingsReadiness | null>(null);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState("");
  const [error, setError] = useState("");
  const [brief, setBrief] = useState<DesignBrief>(EMPTY_BRIEF);
  const [grossArea, setGrossArea] = useState("");
  const [ceilingHeight, setCeilingHeight] = useState("2800");
  const [roomNames, setRoomNames] = useState("");
  const [renderRoom, setRenderRoom] = useState("客餐厅");
  const [renderView, setRenderView] = useState("入口看向客厅");
  const [activeRenderId, setActiveRenderId] = useState("");
  const [editInstruction, setEditInstruction] = useState("");
  const [chatDraft, setChatDraft] = useState("");
  const [chatReply, setChatReply] = useState("");
  const fileInput = useRef<HTMLInputElement>(null);

  const activeStage = stageIndex(project?.stage);
  const selectedDirection = useMemo(
    () => project?.directions.find((item) => item.id === project.style.selected_direction_id) ?? null,
    [project],
  );
  const activeRender = useMemo<RenderAsset | null>(() => {
    if (!project?.renders.length) return null;
    return project.renders.find((item) => item.id === activeRenderId) ?? project.renders.at(-1) ?? null;
  }, [activeRenderId, project]);

  function applyProject(next: ProjectSnapshot) {
    setProject(next);
    setBrief(next.brief ?? EMPTY_BRIEF);
    setGrossArea(next.plan.gross_area_sqm ? String(next.plan.gross_area_sqm) : "");
    setCeilingHeight(String(next.plan.ceiling_height_mm || 2800));
    setRoomNames(next.plan.structure?.rooms?.map((room) => room.name).join("、") ?? "");
    if (next.plan.structure?.rooms?.[0]?.name) setRenderRoom(next.plan.structure.rooms[0].name);
    if (next.renders.length) setActiveRenderId(next.renders[next.renders.length - 1].id);
  }

  useEffect(() => {
    async function boot() {
      try {
        const [readinessResponse, projectsResponse] = await Promise.all([
          fetch(`${API_BASE}/v1/readiness`, { cache: "no-store" }),
          fetch(`${API_BASE}/v1/projects`, { cache: "no-store" }),
        ]);
        if (readinessResponse.ok) {
          const current = await readinessResponse.json() as SettingsReadiness;
          setReadiness(current);
          if (!current.ready) setSettingsOpen(true);
        }
        if (projectsResponse.ok) {
          const projects = await projectsResponse.json() as ProjectSnapshot[];
          const latest = projects.find((item) => item.project_id !== "demo-apartment");
          if (latest) applyProject(latest);
        }
      } catch {
        setError("无法连接本地服务，请检查 Docker 是否正在运行。");
      } finally {
        setLoading(false);
      }
    }
    void boot();
  }, []);

  async function apiError(response: Response, fallback: string) {
    try {
      const body = await response.json() as { detail?: string | { message?: string } };
      if (typeof body.detail === "string") return body.detail;
      if (body.detail?.message) return body.detail.message;
    } catch { /* use fallback */ }
    return fallback;
  }

  async function command(base: ProjectSnapshot, name: string, payload: Record<string, unknown> = {}) {
    const response = await fetch(`${API_BASE}/v1/projects/${base.project_id}/commands`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ command: name, expected_revision: base.revision, payload }),
    });
    if (!response.ok) throw new Error(await apiError(response, "工作流操作失败。"));
    return response.json() as Promise<ProjectSnapshot>;
  }

  async function upload(file: File) {
    if (!readiness?.ready) {
      setSettingsOpen(true);
      return;
    }
    setBusy("正在读取 PDF 并寻找户型区域");
    setError("");
    const form = new FormData();
    form.append("file", file);
    form.append("project_name", `${file.name.replace(/\.pdf$/i, "")} 风格方案`);
    try {
      const response = await fetch(`${API_BASE}/v1/projects/ingest`, { method: "POST", body: form });
      if (!response.ok) throw new Error(await apiError(response, "图纸上传失败。"));
      applyProject(await response.json() as ProjectSnapshot);
    } catch (reason) {
      setError(reason instanceof Error ? reason.message : "图纸上传失败。");
    } finally {
      setBusy("");
      if (fileInput.current) fileInput.current.value = "";
    }
  }

  function onFile(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (file) void upload(file);
  }

  async function chooseRegion(id: string) {
    if (!project) return;
    setBusy("正在建立目标户型");
    setError("");
    try { applyProject(await command(project, "select_region", { region_id: id })); }
    catch (reason) { setError(reason instanceof Error ? reason.message : "选择失败。"); }
    finally { setBusy(""); }
  }

  async function analyzePlan() {
    if (!project) return;
    setBusy("空间模型正在识别房间、动线与采光");
    setError("");
    try {
      const response = await fetch(`${API_BASE}/v1/projects/${project.project_id}/spatial-analysis`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ gross_area_sqm: grossArea ? Number(grossArea) : null }),
      });
      if (!response.ok) throw new Error(await apiError(response, "空间分析失败。"));
      applyProject(await response.json() as ProjectSnapshot);
    } catch (reason) { setError(reason instanceof Error ? reason.message : "空间分析失败。"); }
    finally { setBusy(""); }
  }

  async function confirmStructure() {
    if (!project) return;
    setBusy("正在建立空间骨架和推荐视角");
    setError("");
    try {
      const confirmed = project.stage === "blockout"
        ? project
        : await command(project, "confirm_plan", {
          gross_area_sqm: grossArea ? Number(grossArea) : null,
          ceiling_height_mm: Number(ceilingHeight) || 2800,
          room_names: roomNames.split(/[、,，\n]/).map((item) => item.trim()).filter(Boolean),
        });
      applyProject(await command(confirmed, "build_blockout"));
    } catch (reason) { setError(reason instanceof Error ? reason.message : "结构确认失败。"); }
    finally { setBusy(""); }
  }

  async function createDirections() {
    if (!project) return;
    setBusy("设计总监正在生成三套 Style DNA");
    setError("");
    try {
      const response = await fetch(`${API_BASE}/v1/projects/${project.project_id}/style-directions`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ brief }),
      });
      if (!response.ok) throw new Error(await apiError(response, "风格方向生成失败。"));
      applyProject(await response.json() as ProjectSnapshot);
    } catch (reason) { setError(reason instanceof Error ? reason.message : "风格方向生成失败。"); }
    finally { setBusy(""); }
  }

  async function selectDirection(id: string) {
    if (!project) return;
    setBusy("正在锁定设计方向");
    setError("");
    try { applyProject(await command(project, "select_direction", { direction_id: id })); }
    catch (reason) { setError(reason instanceof Error ? reason.message : "方向选择失败。"); }
    finally { setBusy(""); }
  }

  async function generateRender() {
    if (!project?.style.selected_direction_id) return;
    setBusy("真实生图模型正在生成效果图，通常需要 20 秒到 2 分钟");
    setError("");
    try {
      const response = await fetch(`${API_BASE}/v1/projects/${project.project_id}/renders`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ direction_id: project.style.selected_direction_id, room: renderRoom, view: renderView }),
      });
      if (!response.ok) throw new Error(await apiError(response, "效果图生成失败。"));
      applyProject(await response.json() as ProjectSnapshot);
    } catch (reason) { setError(reason instanceof Error ? reason.message : "效果图生成失败。"); }
    finally { setBusy(""); }
  }

  async function editRender(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!project || !activeRender || !editInstruction.trim()) return;
    setBusy("正在只修改指定内容，并保持其他区域不变");
    setError("");
    try {
      const response = await fetch(`${API_BASE}/v1/projects/${project.project_id}/renders/${activeRender.id}/edit`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ instruction: editInstruction.trim() }),
      });
      if (!response.ok) throw new Error(await apiError(response, "效果图修改失败。"));
      applyProject(await response.json() as ProjectSnapshot);
      setEditInstruction("");
    } catch (reason) { setError(reason instanceof Error ? reason.message : "效果图修改失败。"); }
    finally { setBusy(""); }
  }

  async function chat(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!project || !chatDraft.trim()) return;
    const message = chatDraft.trim();
    setChatDraft("");
    setBusy("设计 Agent 正在理解你的要求");
    try {
      const response = await fetch(`${API_BASE}/v1/projects/${project.project_id}/chat`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ message }),
      });
      if (!response.ok) throw new Error(await apiError(response, "设计 Agent 暂时无法回复。"));
      const result = await response.json() as { project: ProjectSnapshot; reply: string };
      applyProject(result.project);
      setChatReply(result.reply);
    } catch (reason) { setError(reason instanceof Error ? reason.message : "设计 Agent 暂时无法回复。"); }
    finally { setBusy(""); }
  }

  async function completeProject() {
    if (!project) return;
    setBusy("正在整理最终方案");
    try { applyProject(await command(project, "complete_project")); }
    catch (reason) { setError(reason instanceof Error ? reason.message : "方案整理失败。"); }
    finally { setBusy(""); }
  }

  function downloadSummary() {
    if (!project) return;
    const payload = JSON.stringify(project, null, 2);
    const link = document.createElement("a");
    link.href = URL.createObjectURL(new Blob([payload], { type: "application/json" }));
    link.download = `${project.name}-方案记录.json`;
    link.click();
    URL.revokeObjectURL(link.href);
  }

  function renderWorkspace() {
    if (loading) return <div className="product-empty"><CircleNotchIcon className="spin" size={28} /><h2>正在打开工作台</h2></div>;
    if (!project) return (
      <div className="product-empty product-onboarding">
        <div className="onboarding-art"><BuildingsIcon size={58} weight="thin" /></div>
        <p className="product-kicker">从真实户型开始</p>
        <h1>把一张平面图，变成可反复修改的风格方案</h1>
        <p>上传 PDF 后，系统会带你完成空间理解、风格选择、真实生图和多轮修改。</p>
        <button className="product-button primary" type="button" onClick={() => readiness?.ready ? fileInput.current?.click() : setSettingsOpen(true)}>
          <UploadSimpleIcon size={17} />{readiness?.ready ? "选择 PDF 户型图" : "先完成系统设置"}
        </button>
      </div>
    );

    if (project.stage === "region_selection") return (
      <section className="product-stage">
        <header className="stage-header"><div><p>先选对户型</p><h1>这页图纸里，哪一块是你要设计的家？</h1></div><span>点击图中的候选框</span></header>
        <div className="region-stage"><PlanPreview project={project} selectable onSelect={(id) => void chooseRegion(id)} /><aside><h2>识别结果</h2><strong>{project.plan.regions.length} 个候选区域</strong><p>{project.plan.vector_based ? `矢量 PDF，共读取 ${project.plan.vector_element_count.toLocaleString()} 个图形元素。` : "扫描型图纸，已使用视觉区域检测。"}</p><p>选择只会裁剪工作区域，不会修改原 PDF。</p></aside></div>
      </section>
    );

    if (project.stage === "plan_review" || project.stage === "blockout") {
      const structure = project.plan.structure;
      return (
        <section className="product-stage">
          <header className="stage-header"><div><p>空间理解</p><h1>先确认布局事实，再谈风格</h1></div><span>{structure.status === "pending" ? "等待 AI 读图" : structure.degraded ? "可编辑草案" : `由 ${structure.model_name} 识别`}</span></header>
          <div className="structure-layout">
            <PlanPreview project={project} />
            <div className="structure-review">
              {structure.status === "pending" ? (
                  <div className="analysis-callout"><MagicWandIcon size={28} /><h2>让空间模型读懂这套户型</h2><p>它会判断房间、主要动线、采光和布局机会。结果可以在下一步人工修正。</p><label>建筑面积（可选）<input value={grossArea} onChange={(event) => setGrossArea(event.target.value)} inputMode="decimal" placeholder="例如 108" /></label><button className="product-button primary" type="button" onClick={() => void (project.stage === "blockout" ? confirmStructure() : analyzePlan())}>{project.stage === "blockout" ? "继续进入风格需求" : "开始空间分析"}</button></div>
              ) : (
                <>
                  <div className={`analysis-summary ${structure.degraded ? "warning" : ""}`}><strong>{structure.summary}</strong><p>{structure.degraded ? "模型失败并不阻塞流程，请直接修改下面的房间名称。" : structure.circulation}</p></div>
                  <label className="product-field">房间清单<input value={roomNames} onChange={(event) => setRoomNames(event.target.value)} placeholder="客厅、餐厅、主卧、次卧、厨房、卫生间" /><small>用顿号或逗号分隔，可直接修正 AI 判断</small></label>
                  <div className="two-fields"><label className="product-field">建筑面积（㎡）<input value={grossArea} onChange={(event) => setGrossArea(event.target.value)} inputMode="decimal" /></label><label className="product-field">层高（mm）<input value={ceilingHeight} onChange={(event) => setCeilingHeight(event.target.value)} inputMode="numeric" /></label></div>
                  <div className="insight-grid"><div><h3>布局机会</h3>{structure.layout_opportunities.map((item) => <p key={item}><CheckIcon size={13} />{item}</p>)}</div><div><h3>需要留意</h3>{structure.risks.map((item) => <p key={item}><WarningCircleIcon size={13} />{item}</p>)}</div></div>
                  <button className="product-button primary wide" type="button" onClick={() => void confirmStructure()}>确认结构，进入风格需求 <ArrowRightIcon size={16} /></button>
                </>
              )}
            </div>
          </div>
        </section>
      );
    }

    if (project.stage === "style_brief") return (
      <section className="product-stage brief-stage">
        <header className="stage-header"><div><p>风格需求</p><h1>不需要懂专业术语，说清你怎么生活就够了</h1></div><span>约 2 分钟</span></header>
        <div className="brief-form">
          <label className="product-field wide-field">谁会住在这里？<input value={brief.residents} onChange={(event) => setBrief({ ...brief, residents: event.target.value })} placeholder="例如：两位大人、一个 6 岁孩子和一只猫" /></label>
          <ChoiceGroup label="平时最重要的生活场景" options={LIFESTYLE_OPTIONS} values={brief.lifestyle} onChange={(lifestyle) => setBrief({ ...brief, lifestyle })} />
          <ChoiceGroup label="更接近你的风格" options={STYLE_OPTIONS} values={brief.preferred_styles} onChange={(preferred_styles) => setBrief({ ...brief, preferred_styles })} />
          <ChoiceGroup label="喜欢的色彩倾向" options={COLOR_OPTIONS} values={brief.preferred_colors} onChange={(preferred_colors) => setBrief({ ...brief, preferred_colors })} />
          <div className="brief-grid"><label className="product-field">重点设计空间<input value={brief.focus_rooms.join("、")} onChange={(event) => setBrief({ ...brief, focus_rooms: event.target.value.split(/[、,，]/).filter(Boolean) })} placeholder="客餐厅、主卧" /></label><label className="product-field">预算倾向<select value={brief.budget_level} onChange={(event) => setBrief({ ...brief, budget_level: event.target.value })}><option>尽量节制</option><option>适中</option><option>品质优先</option></select></label></div>
          <div className="brief-grid"><label className="product-field">明确不喜欢<input value={brief.disliked_elements.join("、")} onChange={(event) => setBrief({ ...brief, disliked_elements: event.target.value.split(/[、,，]/).filter(Boolean) })} placeholder="例如：亮面石材、复杂吊顶" /></label><label className="product-field">必须保留<input value={brief.must_keep.join("、")} onChange={(event) => setBrief({ ...brief, must_keep: event.target.value.split(/[、,，]/).filter(Boolean) })} placeholder="例如：旧餐桌、钢琴" /></label></div>
          <label className="product-field wide-field">还有什么想告诉设计师？<textarea value={brief.additional_notes} onChange={(event) => setBrief({ ...brief, additional_notes: event.target.value })} placeholder="例如：希望客厅看起来更松弛，但不要像民宿" /></label>
          <button className="product-button primary form-submit" type="button" onClick={() => void createDirections()}>生成三套风格方向 <SparkleIcon size={16} weight="fill" /></button>
        </div>
      </section>
    );

    if (project.stage === "direction_selection") return (
      <section className="product-stage directions-stage">
        <header className="stage-header"><div><p>设计方向</p><h1>三套都能落地，但气质不同</h1></div><span>选择后仍可返回修改需求</span></header>
        <div className="direction-grid">
          {project.directions.map((direction) => (
            <article className="direction-card" key={direction.id}>
              <div className="palette-strip">{direction.palette.map((color) => <span key={color.hex} style={{ background: color.hex }} title={`${color.name}，${color.role}`} />)}</div>
              <div className="direction-body"><h2>{direction.name}</h2><p>{direction.thesis}</p><div className="keyword-row">{direction.keywords.map((item) => <span key={item}>{item}</span>)}</div><dl><dt>材料</dt><dd>{direction.materials.join("、")}</dd><dt>光线</dt><dd>{direction.lighting}</dd></dl><small>{direction.model_name || "设计策略"}</small><button className="product-button primary wide" type="button" onClick={() => void selectDirection(direction.id)}>用这个方向生成效果图</button></div>
            </article>
          ))}
        </div>
      </section>
    );

    if (project.stage === "render_review") return (
      <section className="product-stage render-setup">
        <header className="stage-header"><div><p>效果图生成</p><h1>先生成一个关键视角，再决定是否扩展</h1></div><span>将调用真实生图模型</span></header>
        <div className="render-setup-grid">
          <div className="selected-direction-panel"><div className="palette-strip">{selectedDirection?.palette.map((color) => <span key={color.hex} style={{ background: color.hex }} />)}</div><h2>{selectedDirection?.name}</h2><p>{selectedDirection?.thesis}</p><strong>{selectedDirection?.materials.join("、")}</strong></div>
          <div className="render-controls"><label className="product-field">生成哪个空间？<select value={renderRoom} onChange={(event) => setRenderRoom(event.target.value)}>{project.plan.structure.rooms.map((room) => <option key={room.id}>{room.name}</option>)}<option>客餐厅</option><option>主卧</option></select></label><label className="product-field">相机视角<select value={renderView} onChange={(event) => setRenderView(event.target.value)}><option>入口看向客厅</option><option>客厅看向餐厅</option><option>窗边看向室内</option><option>空间广角主视角</option></select></label><div className="generation-note"><CubeIcon size={20} /><p>系统会把户型裁剪图、空间理解和 Style DNA 一起交给当前模型池中的生图模型。</p></div><button className="product-button primary wide" type="button" onClick={() => void generateRender()}><ImageIcon size={17} />生成真实效果图</button></div>
        </div>
      </section>
    );

    if (project.stage === "editing" || project.stage === "completed") return (
      <section className="product-stage editing-stage">
        <header className="stage-header"><div><p>{project.stage === "completed" ? "方案已完成" : "效果图与修改"}</p><h1>{activeRender?.room}，{activeRender?.view}</h1></div><span>{project.renders.length} 个版本</span></header>
        {activeRender ? (
          <div className="render-workspace">
            <div className="render-main">
              {/* eslint-disable-next-line @next/next/no-img-element -- generated project asset. */}
              <img src={`${API_BASE}/v1/projects/${project.project_id}/renders/${activeRender.id}`} alt={`${activeRender.room} ${activeRender.view} 效果图`} />
              <div className="render-meta"><span>{activeRender.model_name}</span><span>{new Date(activeRender.created_at).toLocaleString("zh-CN")}</span></div>
            </div>
            <aside className="render-sidebar"><h2>版本</h2><div className="version-list">{[...project.renders].reverse().map((render, index) => <button className={render.id === activeRender.id ? "active" : ""} type="button" key={render.id} onClick={() => setActiveRenderId(render.id)}><ImageIcon size={16} /><span><strong>版本 {project.renders.length - index}</strong><small>{render.edit_instruction || `${render.room}，${render.view}`}</small></span></button>)}</div>{project.stage === "editing" ? <form className="edit-form" onSubmit={editRender}><label>只修改什么？<textarea value={editInstruction} onChange={(event) => setEditInstruction(event.target.value)} placeholder="例如：把沙发改为更低矮的米灰色模块沙发，其他都不变" /></label><button className="product-button primary wide" type="submit" disabled={!editInstruction.trim()}><PencilSimpleIcon size={16} />生成新版本</button><button className="product-button secondary wide" type="button" onClick={() => void completeProject()}>确认当前方案</button></form> : <button className="product-button primary wide" type="button" onClick={downloadSummary}><DownloadSimpleIcon size={16} />导出方案记录</button>}</aside>
          </div>
        ) : <div className="product-empty"><ImageIcon size={36} /><h2>还没有效果图</h2></div>}
      </section>
    );

    return <div className="product-empty"><CubeIcon size={34} /><h2>正在准备下一阶段</h2></div>;
  }

  return (
    <main className="product-shell">
      <header className="product-topbar">
        <div className="product-brand"><span><BuildingsIcon size={19} weight="fill" /></span><div><strong>住境 AI</strong><small>{project?.name ?? "住宅风格设计工作台"}</small></div></div>
        <div className="product-top-actions">
          {project ? <button className="product-button ghost" type="button" onClick={() => setProject(null)}><PlusIcon size={15} />新方案</button> : null}
          <button className="product-button secondary" type="button" onClick={() => setSettingsOpen(true)}><GearSixIcon size={16} />系统设置</button>
        </div>
        <input ref={fileInput} className="visually-hidden" type="file" accept="application/pdf,.pdf" onChange={onFile} />
      </header>

      <div className="product-body">
        <aside className="product-rail">
          <div className="rail-progress"><strong>{project ? activeStage + 1 : 0}</strong><span>/ {STAGES.length}</span></div>
          <nav>{STAGES.map((stage, index) => <div key={stage.label} className={index < activeStage ? "complete" : index === activeStage && project ? "active" : "pending"}><span>{index < activeStage ? <CheckIcon size={12} weight="bold" /> : index + 1}</span><p><strong>{stage.label}</strong><small>{stage.detail}</small></p></div>)}</nav>
          {project ? <button className="change-plan" type="button" onClick={() => fileInput.current?.click()}><UploadSimpleIcon size={15} />更换图纸</button> : null}
        </aside>

        <div className="product-center">
          {busy ? <div className="busy-banner"><CircleNotchIcon className="spin" size={16} /><span>{busy}</span></div> : null}
          {error ? <div className="error-banner"><WarningCircleIcon size={17} /><span>{error}</span><button type="button" onClick={() => setError("")}>关闭</button></div> : null}
          {renderWorkspace()}
        </div>

        <aside className="agent-panel">
          <div className="agent-heading"><span><SparkleIcon size={15} weight="fill" /></span><div><strong>设计 Agent</strong><small>{readiness?.ready ? "模型与存储已就绪" : "等待系统配置"}</small></div></div>
          <div className="agent-stream">
            {!project ? <div className="agent-message"><p>上传户型图后，我会在每个关键决策点给出判断，也会主动追问缺失信息。</p></div> : null}
            {project?.events.slice(-6).map((event) => <div key={event.id} className={`agent-message ${event.kind === "user" ? "user" : ""}`}><small>{event.kind === "user" ? "你" : event.kind === "assistant" ? "设计 Agent" : "工作记录"}</small><p>{event.message}</p></div>)}
            {chatReply && !project?.events.some((event) => event.message === chatReply) ? <div className="agent-message"><p>{chatReply}</p></div> : null}
          </div>
          <form className="agent-input" onSubmit={chat}><textarea value={chatDraft} onChange={(event) => setChatDraft(event.target.value)} placeholder={project ? "告诉我你的偏好，或问我下一步怎么选" : "先上传图纸后开始对话"} disabled={!project || Boolean(busy)} /><button type="submit" disabled={!project || !chatDraft.trim() || Boolean(busy)} aria-label="发送"><PaperPlaneTiltIcon size={16} weight="fill" /></button></form>
        </aside>
      </div>

      <SettingsCenter open={settingsOpen} onClose={() => setSettingsOpen(false)} onReadinessChange={setReadiness} />
    </main>
  );
}
