import { useCallback, useEffect, useRef, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { ApiRequestError } from '../../api/client';
import { designApi, renderApi } from '../../api/endpoints';
import { subscribeRenderJob } from '../../api/websocket';
import { Button } from '../../components/ui/Button';
import { AiLabel } from '../../components/ui/Badge';
import { AiImage } from '../../components/ui/AiImage';
import { CompareSlider } from '../../components/ui/CompareSlider';
import type { ComplianceReport, DesignSpec, RenderJobDto, RenderJobRequest } from '../../api/types';
import { AFTER_PLACEHOLDER, AFTER_SAMPLE, BEFORE_EMPTY_HALL, MOCK_SHOT_IMG } from './placeholders';
import {
  REROOM_STYLES,
  downscaleImage,
  reroomApi,
  MAX_UPLOAD_BYTES,
} from './reroomApi';
import './studio.css';

/*
 * SCR-06 부스 설계 스튜디오 (M3 스펙 + M5 렌더). Stitch booth_design_studio 이식.
 * - 좌: 스펙 아코디언 폼 → precheck(완성 API)로 사전검증. 중앙: 4샷 그리드(S1~S4) + Before/After(S5).
 * - "예상 사진 생성" → render POST(완성 큐잉) → WebSocket /topic/render/{jobId} 로 타일 교체.
 */

const SHOTS = [
  { preset: 'S1', label: 'S1 부스 정면' },
  { preset: 'S2', label: 'S2 야간 점등' },
  { preset: 'S3', label: 'S3 통로 뷰' },
  { preset: 'S4', label: 'S4 부스 내부' },
] as const;

const DEFAULT_SPEC: DesignSpec = {
  boothType: 'independent',
  industry: '로봇/제조',
  budget: 30000000,
  zones: [
    { type: 'demo', ratioPercent: 40 },
    { type: 'consult', ratioPercent: 30 },
    { type: 'reception', ratioPercent: 20 },
    { type: 'storage', ratioPercent: 10 },
  ],
  wallHeightM: 4.2,
  signageText: '한빛로보틱스',
  rigging: { use: true, heightM: 7.0 },
  mezzanineAreaRatio: 0.3,
  materials: [{ part: 'wall', finish: 'matte_white', fireRetardant: true }],
  lightingMode: 'night',
  usesDesignatedLightingOnly: true,
};

type Section = 'basic' | 'zones' | 'structure' | 'material' | 'lighting';

export function BoothDesignStudioPage() {
  const { eventId = '', boothId = '' } = useParams();
  const navigate = useNavigate();

  const [spec, setSpec] = useState<DesignSpec>(DEFAULT_SPEC);
  const [open, setOpen] = useState<Record<Section, boolean>>({
    basic: true,
    zones: false,
    structure: true,
    material: false,
    lighting: false,
  });
  const [report, setReport] = useState<ComplianceReport | null>(null);
  const [prechecking, setPrechecking] = useState(false);
  const [jobs, setJobs] = useState<Record<string, RenderJobDto>>({}); // preset → job
  const [generating, setGenerating] = useState(false);
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [confirmAgree, setConfirmAgree] = useState(false);
  const [notice, setNotice] = useState<string | null>(null);

  // ── 사진 시안(ReRoom, image-to-image) — 소유자 지시 13.2 ──
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [refPreview, setRefPreview] = useState<string | null>(null); // 로컬 objectURL(Before)
  const [refId, setRefId] = useState<string | null>(null); // 서버 참조 이미지 id
  const [refUploading, setRefUploading] = useState(false);
  const [reroomStyle, setReroomStyle] = useState<string>('modern');
  const [reroomInstruction, setReroomInstruction] = useState('');
  const [reroomJob, setReroomJob] = useState<RenderJobDto | null>(null);
  const [reroomBusy, setReroomBusy] = useState(false);
  const [reroomError, setReroomError] = useState<string | null>(null);
  const [dragOver, setDragOver] = useState(false);

  // 초기 설계안 로드(501이면 degraded 기본 스펙 유지).
  useEffect(() => {
    let alive = true;
    designApi
      .get(eventId, boothId)
      .then((d) => alive && setSpec(d.spec))
      .catch(() => {
        /* 501/미존재 → 기본 스펙 시연 */
      });
    return () => {
      alive = false;
    };
  }, [eventId, boothId]);

  // 발행된 렌더잡 WebSocket 구독.
  useEffect(() => {
    const ids = Object.values(jobs)
      .map((j) => j.jobId)
      .filter(Boolean);
    if (ids.length === 0) return;
    const unsubs = ids.map((id) =>
      subscribeRenderJob(id, (job) => {
        setJobs((prev) => ({ ...prev, [job.shotPreset]: job }));
      }),
    );
    return () => unsubs.forEach((u) => u());
  }, [jobs]);

  // 사진 시안 잡: WebSocket 구독 + 폴백 폴링(완료/실패까지).
  useEffect(() => {
    const jobId = reroomJob?.jobId;
    if (!jobId || reroomJob?.status === 'DONE' || reroomJob?.status === 'FAILED') return;
    const unsub = subscribeRenderJob(jobId, (job) => setReroomJob(job));
    const timer = window.setInterval(async () => {
      try {
        setReroomJob(await reroomApi.status(eventId, jobId));
      } catch {
        /* 폴백 폴링 실패는 무시(WebSocket 우선) */
      }
    }, 4000);
    return () => {
      unsub();
      window.clearInterval(timer);
    };
  }, [reroomJob?.jobId, reroomJob?.status, eventId]);

  // 언마운트 시 미리보기 objectURL 정리.
  useEffect(() => {
    return () => {
      if (refPreview) URL.revokeObjectURL(refPreview);
    };
  }, [refPreview]);

  // 참조 이미지 선택 → 1024px 다운스케일 → 즉시 업로드(referenceId 확보).
  const handleRefFile = useCallback(
    async (file: File | undefined | null) => {
      if (!file) return;
      setReroomError(null);
      if (!file.type.startsWith('image/')) {
        setReroomError('이미지 파일만 업로드할 수 있습니다.');
        return;
      }
      if (file.size > MAX_UPLOAD_BYTES) {
        setReroomError('참조 이미지는 10MB 이하만 업로드할 수 있습니다.');
        return;
      }
      setRefUploading(true);
      setReroomJob(null);
      setRefId(null);
      try {
        const blob = await downscaleImage(file);
        setRefPreview((prev) => {
          if (prev) URL.revokeObjectURL(prev);
          return URL.createObjectURL(blob);
        });
        const res = await reroomApi.uploadReference(eventId, boothId, blob);
        setRefId(res.referenceId);
      } catch (err) {
        setReroomError(
          err instanceof ApiRequestError ? err.message : '참조 이미지 업로드에 실패했습니다.',
        );
      } finally {
        setRefUploading(false);
      }
    },
    [eventId, boothId],
  );

  const generateReroom = useCallback(async () => {
    if (!refId) {
      setReroomError('먼저 빈 부스/공간 사진을 업로드하세요.');
      return;
    }
    setReroomBusy(true);
    setReroomError(null);
    try {
      const job = await reroomApi.render(eventId, boothId, {
        referenceId: refId,
        style: reroomStyle,
        instruction: reroomInstruction.trim() || undefined,
      });
      setReroomJob(job);
    } catch (err) {
      if (err instanceof ApiRequestError && err.code === 'RENDER_QUOTA_EXCEEDED') {
        setReroomError('행사 이미지 생성 쿼터가 소진되었습니다.');
      } else {
        setReroomError(err instanceof ApiRequestError ? err.message : '시안 생성 중 오류가 발생했습니다.');
      }
    } finally {
      setReroomBusy(false);
    }
  }, [eventId, boothId, refId, reroomStyle, reroomInstruction]);

  const runPrecheck = useCallback(async () => {
    setPrechecking(true);
    setNotice(null);
    try {
      const r = await designApi.precheck(eventId, boothId, spec);
      setReport(r);
    } catch (err) {
      setNotice(
        err instanceof ApiRequestError ? err.message : '사전 검증 중 오류가 발생했습니다.',
      );
    } finally {
      setPrechecking(false);
    }
  }, [eventId, boothId, spec]);

  const buildScene = useCallback(
    (): RenderJobRequest['scene'] => ({
      hall: { id: 'H7', dims_m: [126, 90], ceiling_m: 12 },
      booth: { id: boothId || 'A-102', size_m: [6, 3], type: spec.boothType },
      design: { signage: { text: spec.signageText } },
      lighting: { mode: spec.lightingMode },
    }),
    [boothId, spec.boothType, spec.signageText, spec.lightingMode],
  );

  const generateShots = useCallback(async () => {
    setGenerating(true);
    setNotice(null);
    const scene = buildScene();
    // S1·S2를 우선 발행(S3·S4는 온디맨드 타일에서 개별 생성).
    for (const preset of ['S1', 'S2'] as const) {
      try {
        const job = await renderApi.create(eventId, boothId, { shotPreset: preset, scene });
        setJobs((prev) => ({ ...prev, [preset]: job }));
      } catch (err) {
        if (err instanceof ApiRequestError && err.code === 'RENDER_QUOTA_EXCEEDED') {
          setNotice('행사 이미지 생성 쿼터가 소진되었습니다.');
          break;
        }
        if (err instanceof ApiRequestError && err.code === 'NOT_IMPLEMENTED') {
          setNotice('렌더 이력 저장이 준비 중입니다(큐잉만 동작).');
        } else {
          setNotice(err instanceof ApiRequestError ? err.message : '예상 사진 생성 중 오류.');
        }
      }
    }
    setGenerating(false);
    // 병행: precheck 갱신
    void runPrecheck();
  }, [eventId, boothId, buildScene, runPrecheck]);

  const generateSingle = useCallback(
    async (preset: string) => {
      setNotice(null);
      try {
        const job = await renderApi.create(eventId, boothId, {
          shotPreset: preset,
          scene: buildScene(),
        });
        setJobs((prev) => ({ ...prev, [preset]: job }));
      } catch (err) {
        setNotice(err instanceof ApiRequestError ? err.message : '생성 중 오류가 발생했습니다.');
      }
    },
    [eventId, boothId, buildScene],
  );

  const s1 = jobs.S1;
  const afterReal = s1?.status === 'DONE' && s1.imageUrl ? s1.imageUrl : null;
  const afterSrc = afterReal ?? AFTER_SAMPLE;

  const passCount = report?.passCount ?? 0;
  const warnCount = report?.warnCount ?? 0;
  const blockCount = report?.blockCount ?? 0;
  const submittable = report?.submittable ?? false;

  return (
    <div className="kx-studio">
      {/* 상단 컨텍스트 바 */}
      <header className="kx-studio__head">
        <div className="kx-studio__ctx">
          <button
            type="button"
            className="kx-studio__back"
            aria-label="뒤로"
            onClick={() => navigate(-1)}
          >
            ←
          </button>
          <div>
            <h2>부스 {boothId || 'A-102'} · 독립부스 6×3m</h2>
            <span className="kx-studio__ctx-sub">높이 제한 5m</span>
          </div>
          <span className="kx-studio__ctx-div" aria-hidden="true" />
          <select
            className="kx-studio__ver-select"
            aria-label="설계 버전"
            defaultValue="v2"
          >
            <option value="v2">설계 v2</option>
            <option value="v1">설계 v1</option>
          </select>
        </div>
        <Button variant="ai" leadingIcon="✦" onClick={generateShots} disabled={generating}>
          {generating ? '생성 요청 중…' : '예상 사진 생성'}
        </Button>
      </header>

      <div className="kx-studio__body">
        {/* 좌: 스펙 아코디언 */}
        <aside className="kx-studio__spec" aria-label="설계 스펙">
          <Accordion
            title="기본 정보"
            open={open.basic}
            onToggle={() => setOpen((o) => ({ ...o, basic: !o.basic }))}
          >
            <Field label="업종">
              <input
                value={spec.industry}
                onChange={(e) => setSpec((s) => ({ ...s, industry: e.target.value }))}
              />
            </Field>
            <Field label="예산 (₩)">
              <input
                type="number"
                className="tnum"
                value={spec.budget}
                onChange={(e) => setSpec((s) => ({ ...s, budget: Number(e.target.value) }))}
              />
            </Field>
          </Accordion>

          <Accordion
            title="공간 구성"
            open={open.zones}
            onToggle={() => setOpen((o) => ({ ...o, zones: !o.zones }))}
          >
            {spec.zones.map((z, i) => (
              <Field key={z.type} label={ZONE_LABEL[z.type] ?? z.type}>
                <div className="kx-studio__ratio">
                  <input
                    type="range"
                    min={0}
                    max={100}
                    value={z.ratioPercent}
                    aria-label={`${ZONE_LABEL[z.type] ?? z.type} 비율`}
                    onChange={(e) =>
                      setSpec((s) => ({
                        ...s,
                        zones: s.zones.map((x, j) =>
                          j === i ? { ...x, ratioPercent: Number(e.target.value) } : x,
                        ),
                      }))
                    }
                  />
                  <span className="tnum">{z.ratioPercent}%</span>
                </div>
              </Field>
            ))}
          </Accordion>

          <Accordion
            title="구조"
            open={open.structure}
            onToggle={() => setOpen((o) => ({ ...o, structure: !o.structure }))}
          >
            <Field label={`벽체 높이 (${spec.wallHeightM}m · 최대 5m)`}>
              <input
                type="range"
                min={2}
                max={6}
                step={0.1}
                value={spec.wallHeightM}
                aria-label="벽체 높이"
                onChange={(e) => setSpec((s) => ({ ...s, wallHeightM: Number(e.target.value) }))}
              />
              {spec.wallHeightM > 5 && (
                <p className="kx-studio__inline-warn">높이 5m 초과 — 규정 차단 대상</p>
              )}
            </Field>
            <Field label="간판 문구">
              <input
                value={spec.signageText}
                onChange={(e) => setSpec((s) => ({ ...s, signageText: e.target.value }))}
              />
            </Field>
            <label className="kx-studio__toggle">
              <input
                type="checkbox"
                checked={spec.rigging.use}
                onChange={(e) =>
                  setSpec((s) => ({ ...s, rigging: { ...s.rigging, use: e.target.checked } }))
                }
              />
              트러스/리깅 사용
            </label>
            {spec.rigging.use && (
              <p className="kx-studio__inline-warn">
                리깅 6.5~8.5m: 구조계산서 D-7 제출 필요
              </p>
            )}
          </Accordion>

          <Accordion
            title="자재"
            open={open.material}
            onToggle={() => setOpen((o) => ({ ...o, material: !o.material }))}
          >
            <Field label="벽체 마감">
              <select
                value={spec.materials[0]?.finish}
                onChange={(e) =>
                  setSpec((s) => ({
                    ...s,
                    materials: [{ ...s.materials[0], finish: e.target.value }],
                  }))
                }
              >
                <option value="matte_white">무광 화이트</option>
                <option value="wood">우드</option>
                <option value="metal">메탈</option>
              </select>
            </Field>
            <label className="kx-studio__toggle kx-studio__toggle--req">
              <input
                type="checkbox"
                checked={spec.materials[0]?.fireRetardant ?? false}
                onChange={(e) =>
                  setSpec((s) => ({
                    ...s,
                    materials: [{ ...s.materials[0], fireRetardant: e.target.checked }],
                  }))
                }
              />
              방염 자재 사용 확인 (필수)
            </label>
          </Accordion>

          <Accordion
            title="조명"
            open={open.lighting}
            onToggle={() => setOpen((o) => ({ ...o, lighting: !o.lighting }))}
          >
            <div className="kx-studio__seg" role="radiogroup" aria-label="조명 모드">
              {(['day', 'night'] as const).map((m) => (
                <button
                  key={m}
                  role="radio"
                  aria-checked={spec.lightingMode === m}
                  className={spec.lightingMode === m ? 'is-active' : ''}
                  onClick={() => setSpec((s) => ({ ...s, lightingMode: m }))}
                >
                  {m === 'day' ? '주간' : '야간'}
                </button>
              ))}
            </div>
          </Accordion>
        </aside>

        {/* 중앙: 4샷 그리드 + Before/After */}
        <section className="kx-studio__hero">
          <div className="kx-studio__grid">
            {SHOTS.map((shot) => {
              const job = jobs[shot.preset];
              return (
                <div className="kx-studio__tile" key={shot.preset}>
                  {job ? (
                    <AiImage
                      imageUrl={job.imageUrl}
                      status={job.status}
                      watermarkText={job.watermarkText}
                      notice={job.notice}
                      shotLabel={shot.label}
                      versionTag="설계 v2"
                      onRetry={() => generateSingle(shot.preset)}
                      alt={`${shot.label} 예상 이미지`}
                    />
                  ) : MOCK_SHOT_IMG[shot.preset] ? (
                    <AiImage
                      imageUrl={MOCK_SHOT_IMG[shot.preset]}
                      status="DONE"
                      watermarkText="AI 생성 예상 이미지"
                      notice="AI 예시 이미지 — 실제 부스 렌더는 ‘이 뷰 생성’으로 요청하세요. 시공 기준은 도면입니다."
                      shotLabel={shot.label}
                      versionTag="설계 v2"
                      sample
                      onGenerate={() => generateSingle(shot.preset)}
                      alt={`${shot.label} 예시 이미지`}
                    />
                  ) : (
                    <div className="kx-studio__tile-empty">
                      <div className="kx-studio__tile-icon" aria-hidden="true">✦</div>
                      <span className="kx-studio__tile-label">{shot.label}</span>
                      <button onClick={() => generateSingle(shot.preset)}>✦ 클릭해 생성</button>
                    </div>
                  )}
                </div>
              );
            })}
          </div>

          {/* Before/After 슬라이더 (S5) */}
          <div className="kx-studio__compare">
            <div className="kx-studio__compare-head">
              <AiLabel>S5 Before / After</AiLabel>
              {!afterReal && <span className="kx-studio__compare-note">예시 · S1 생성 시 실 이미지로 교체</span>}
            </div>
            <CompareSlider
              beforeSrc={BEFORE_EMPTY_HALL}
              afterSrc={afterSrc || AFTER_PLACEHOLDER}
              beforeLabel="시공 전"
              afterLabel="시공 후"
              afterOverlay={
                <>
                  <div className="kx-studio__wm" aria-hidden="true">
                    {s1?.watermarkText ?? 'AI 생성 예상 이미지'}
                  </div>
                  <span className="kx-studio__after-ai">
                    <AiLabel>{afterReal ? 'AI 생성' : '예시'}</AiLabel>
                  </span>
                </>
              }
            />
            <p className="kx-studio__compare-notice">
              {s1?.notice ??
                'AI 생성 이미지는 계약·심사 서류에 사용할 수 없습니다 — 시공 기준은 도면입니다'}
            </p>
          </div>
        </section>
      </div>

      {/* 사진 시안(AI) — ReRoomAI 방식 image-to-image (소유자 지시 13.2) */}
      <section className="kx-reroom" aria-label="사진 시안 (AI)">
        <div className="kx-reroom__head">
          <AiLabel>사진 시안 (AI)</AiLabel>
          <p className="kx-reroom__sub">
            빈 부스·공간 사진을 올리면 골격·구도는 그대로 두고 스타일만 바꾼 “시공 후” 예상 사진을 생성합니다.
            시공 기준은 도면이며, 생성 이미지는 참고용입니다.
          </p>
        </div>

        <div className="kx-reroom__body">
          {/* 01 업로드 */}
          <div className="kx-reroom__col">
            <span className="kx-reroom__step">01 빈 부스 사진</span>
            <div
              className={`kx-reroom__drop${dragOver ? ' is-over' : ''}${
                refPreview ? ' has-img' : ''
              }`}
              role="button"
              tabIndex={0}
              aria-label="참조 이미지 업로드"
              onClick={() => fileInputRef.current?.click()}
              onKeyDown={(e) => {
                if (e.key === 'Enter' || e.key === ' ') {
                  e.preventDefault();
                  fileInputRef.current?.click();
                }
              }}
              onDragOver={(e) => {
                e.preventDefault();
                setDragOver(true);
              }}
              onDragLeave={() => setDragOver(false)}
              onDrop={(e) => {
                e.preventDefault();
                setDragOver(false);
                void handleRefFile(e.dataTransfer.files?.[0]);
              }}
            >
              {refPreview ? (
                <img src={refPreview} alt="참조 이미지 미리보기" className="kx-reroom__preview" />
              ) : (
                <span className="kx-reroom__drop-hint">
                  <span className="kx-reroom__drop-plus" aria-hidden="true">
                    ＋
                  </span>
                  사진을 끌어다 놓거나 클릭해 업로드
                  <small>JPG · PNG · WebP · 10MB 이하</small>
                </span>
              )}
              {refUploading && (
                <span className="kx-reroom__uploading" aria-live="polite">
                  업로드 중…
                </span>
              )}
            </div>
            <input
              ref={fileInputRef}
              type="file"
              accept="image/*"
              hidden
              onChange={(e) => void handleRefFile(e.target.files?.[0])}
            />
          </div>

          {/* 02 스타일 + 03 지시 + 생성 */}
          <div className="kx-reroom__col kx-reroom__col--wide">
            <span className="kx-reroom__step">02 스타일</span>
            <div className="kx-reroom__styles" role="radiogroup" aria-label="시안 스타일">
              {REROOM_STYLES.map((s) => (
                <button
                  key={s.id}
                  type="button"
                  role="radio"
                  aria-checked={reroomStyle === s.id}
                  className={`kx-reroom__style${reroomStyle === s.id ? ' is-active' : ''}`}
                  onClick={() => setReroomStyle(s.id)}
                >
                  <span className="kx-reroom__swatch" aria-hidden="true">
                    {s.swatch.map((c, i) => (
                      <i key={i} style={{ background: c }} />
                    ))}
                  </span>
                  {s.label}
                </button>
              ))}
            </div>

            <span className="kx-reroom__step">03 추가 지시 (선택)</span>
            <textarea
              className="kx-reroom__instruction"
              rows={2}
              maxLength={500}
              placeholder="예: 파란색 브랜드 월과 로봇 데모 존을 강조해줘"
              value={reroomInstruction}
              onChange={(e) => setReroomInstruction(e.target.value)}
            />

            <div className="kx-reroom__actions">
              <Button
                variant="ai"
                leadingIcon="✦"
                onClick={generateReroom}
                disabled={!refId || refUploading || reroomBusy}
              >
                {reroomBusy ? '시안 생성 요청 중…' : '사진 시안 생성'}
              </Button>
              {reroomError && (
                <p className="kx-reroom__err" role="status">
                  {reroomError}
                </p>
              )}
            </div>
          </div>
        </div>

        {/* 결과 Before/After */}
        {reroomJob && (
          <div className="kx-reroom__result">
            {reroomJob.status === 'DONE' && reroomJob.imageUrl && refPreview ? (
              <CompareSlider
                beforeSrc={refPreview}
                afterSrc={reroomJob.imageUrl}
                beforeLabel="업로드(빈 공간)"
                afterLabel="AI 시안"
                afterOverlay={
                  <>
                    <div className="kx-studio__wm" aria-hidden="true">
                      {reroomJob.watermarkText}
                    </div>
                    <span className="kx-studio__after-ai">
                      <AiLabel>AI 생성</AiLabel>
                    </span>
                  </>
                }
              />
            ) : (
              <AiImage
                imageUrl={reroomJob.imageUrl}
                status={reroomJob.status}
                watermarkText={reroomJob.watermarkText}
                notice={reroomJob.notice}
                shotLabel="사진 시안"
                onRetry={generateReroom}
                alt="사진 시안 예상 이미지"
              />
            )}
            <p className="kx-reroom__notice">{reroomJob.notice}</p>
          </div>
        )}
      </section>

      {/* 하단 고정 바: 규정 사전검증 요약 + 컨펌 CTA */}
      <footer className="kx-studio__footer">
        <div className="kx-studio__precheck">
          <Button variant="ghost" onClick={runPrecheck} disabled={prechecking}>
            {prechecking ? '검증 중…' : '규정 사전검증'}
          </Button>
          {report ? (
            <div className="kx-studio__chips tnum">
              <span className="kx-chip kx-chip--pass">통과 {passCount}</span>
              {warnCount > 0 && <span className="kx-chip kx-chip--warn">경고 {warnCount}</span>}
              {blockCount > 0 && <span className="kx-chip kx-chip--block">차단 {blockCount}</span>}
              {report.violations.some((v) => v.requiresDocument) && (
                <span className="kx-chip kx-chip--doc">구조계산서 D-7 필요</span>
              )}
            </div>
          ) : (
            <span className="kx-studio__precheck-hint">사전검증을 실행하세요</span>
          )}
        </div>
        <Button disabled={!!report && !submittable} onClick={() => setConfirmOpen(true)}>
          장치업체에 컨펌 요청
        </Button>
      </footer>

      {notice && (
        <p className="kx-studio__banner" role="status">
          {notice}
        </p>
      )}

      {/* 컨펌 모달 — "시공 기준은 도면입니다" 동의 필수 */}
      {confirmOpen && (
        <div className="kx-modal" role="dialog" aria-modal="true" aria-labelledby="confirm-title">
          <div className="kx-modal__backdrop" onClick={() => setConfirmOpen(false)} />
          <div className="kx-studio__confirm">
            <h3 id="confirm-title">컨펌 요청</h3>
            <p>
              장치업체에 이 설계안의 컨펌을 요청합니다. AI 예상 사진은 참고용이며 실제 시공 기준은
              도면입니다.
            </p>
            <label className="kx-studio__toggle kx-studio__toggle--req">
              <input
                type="checkbox"
                checked={confirmAgree}
                onChange={(e) => setConfirmAgree(e.target.checked)}
              />
              시공 기준은 도면임을 확인했습니다 (필수)
            </label>
            <div className="kx-modal__actions">
              <Button variant="ghost" onClick={() => setConfirmOpen(false)}>
                취소
              </Button>
              <Button
                disabled={!confirmAgree}
                onClick={() => {
                  setConfirmOpen(false);
                  setNotice('컨펌 요청이 전송되었습니다.');
                }}
              >
                컨펌 요청 전송
              </Button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

const ZONE_LABEL: Record<string, string> = {
  demo: '시연존',
  consult: '상담존',
  reception: '안내데스크',
  storage: '창고',
};

function Accordion({
  title,
  open,
  onToggle,
  children,
}: {
  title: string;
  open: boolean;
  onToggle: () => void;
  children: React.ReactNode;
}) {
  return (
    <section className="kx-acc">
      <button
        className="kx-acc__head"
        aria-expanded={open}
        onClick={onToggle}
        type="button"
      >
        <span>{title}</span>
        <span className="kx-acc__chevron" aria-hidden="true">
          {open ? '▾' : '▸'}
        </span>
      </button>
      {open && <div className="kx-acc__body">{children}</div>}
    </section>
  );
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <label className="kx-field-block">
      <span className="kx-field-block__label">{label}</span>
      {children}
    </label>
  );
}
