/*
 * SCR-35 CMS 콘텐츠·게시 워크플로 [M17]. 참조: design.md §3 SCR-35.
 * 좌: 콘텐츠 목록(상태 배지) · 중: 에디터(제목·블록·미디어) · 우: 게시 워크플로(전이 draft→review→approved→published·예약·사이니지 토글).
 * ★실 API 전환: GET/POST /api/cms/contents · PATCH /api/cms/contents/{id}/status?value=. 상태 전이 실동작(역전이 400 방지 — 전진 버튼만 노출).
 */
import { useEffect, useMemo, useState } from 'react';
import { Button } from '../../components/ui/Button';
import { AiLabel } from '../../components/ui/Badge';
import { ApiRequestError } from '../../api/client';
import { cmsApi, type CmsContent, type FlowStatus } from './cmsApi';
import {
  IconDocument,
  IconSpark,
  IconCalendar,
  IconCheckCircle,
  IconImage,
  IconPlus,
  IconWarning,
} from '../../components/ui/icons';
import './cms.css';

const STATUS_META: Record<FlowStatus, { label: string; cls: string }> = {
  draft: { label: '초안', cls: 'kx-cms-pill--draft' },
  review: { label: '검수 중', cls: 'kx-cms-pill--review' },
  approved: { label: '승인', cls: 'kx-cms-pill--approved' },
  published: { label: '게시 완료', cls: 'kx-cms-pill--published' },
};
const FLOW_ORDER: FlowStatus[] = ['draft', 'review', 'approved', 'published'];

// 툴바용 소형 인라인 아이콘(stroke, currentColor) — 라이브러리 미보유분.
function ToolIcon({ d }: { d: string }) {
  return (
    <svg width={18} height={18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d={d} />
    </svg>
  );
}
const TOOLS = [
  { title: '굵게', d: 'M6 4h8a4 4 0 0 1 0 8H6zM6 12h9a4 4 0 0 1 0 8H6z' },
  { title: '기울임', d: 'M19 4h-9M14 20H5M15 4L9 20' },
  { title: '링크', d: 'M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1' },
  { title: '목록', d: 'M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01' },
];

function fmtDate(iso: string | null): string {
  if (!iso) return '-';
  const d = new Date(iso);
  return Number.isNaN(d.getTime()) ? '-' : d.toLocaleString('ko-KR', { dateStyle: 'medium', timeStyle: 'short' });
}

// ISO(UTC, ...Z) → datetime-local 입력값(yyyy-MM-ddTHH:mm, 로컬 시각). 예약 게시 시각 편집용.
function toLocalInput(iso: string | null): string {
  if (!iso) return '';
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return '';
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

export function CmsWorkflowPage() {
  const [items, setItems] = useState<CmsContent[]>([]);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const [signage, setSignage] = useState(true);
  const [mailing, setMailing] = useState(false);
  const [schedInput, setSchedInput] = useState('');
  const [schedSaving, setSchedSaving] = useState(false);

  async function reload(keepSelection = true) {
    setLoading(true);
    setError(null);
    try {
      const res = await cmsApi.listContents({ size: 100 });
      setItems(res.items);
      if (!keepSelection || !res.items.some((c) => c.id === selectedId)) {
        setSelectedId(res.items[0]?.id ?? null);
      }
    } catch (e) {
      setError(e instanceof ApiRequestError ? e.message : '콘텐츠를 불러오지 못했습니다.');
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void reload(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const selected = useMemo(
    () => items.find((c) => c.id === selectedId) ?? null,
    [items, selectedId],
  );

  // 선택 콘텐츠가 바뀌면 예약 시각 입력을 서버 값으로 동기화.
  useEffect(() => {
    setSchedInput(toLocalInput(selected?.scheduledAt ?? null));
  }, [selectedId, selected?.scheduledAt]);

  // 예약 게시 시각 저장(비우면 예약 해제). PUT /api/cms/contents/{id} — 제목은 서버 필수라 현재 제목을 함께 전송.
  async function saveSchedule() {
    if (!selected) return;
    setSchedSaving(true);
    setError(null);
    try {
      const iso = schedInput ? new Date(schedInput).toISOString() : null;
      const updated = await cmsApi.updateContent(selected.id, { title: selected.title, scheduledAt: iso });
      setItems((prev) => prev.map((c) => (c.id === updated.id ? updated : c)));
    } catch (e) {
      setError(e instanceof ApiRequestError ? e.message : '예약 시각 저장에 실패했습니다.');
    } finally {
      setSchedSaving(false);
    }
  }

  async function advance(next: FlowStatus) {
    if (!selected) return;
    setBusy(true);
    setError(null);
    try {
      const updated = await cmsApi.transition(selected.id, next);
      setItems((prev) => prev.map((c) => (c.id === updated.id ? updated : c)));
    } catch (e) {
      setError(e instanceof ApiRequestError ? e.message : '상태 전이에 실패했습니다.');
    } finally {
      setBusy(false);
    }
  }

  async function createDraft() {
    setBusy(true);
    setError(null);
    try {
      const created = await cmsApi.createContent({ title: '새 콘텐츠 (초안)', contentType: 'PAGE' });
      setItems((prev) => [created, ...prev]);
      setSelectedId(created.id);
    } catch (e) {
      setError(e instanceof ApiRequestError ? e.message : '콘텐츠 생성에 실패했습니다.');
    } finally {
      setBusy(false);
    }
  }

  const curIdx = selected ? FLOW_ORDER.indexOf(selected.status) : -1;

  return (
    <div className="kx-page">
      <header className="kx-cms__head">
        <div>
          <h1 className="kx-cms__title">콘텐츠 (CMS)</h1>
          <p className="kx-cms__subtitle">
            헤드리스 콘텐츠 · 게시 워크플로(초안 → 검수 → 승인 → 게시) · 예약 게시 · 다국어
          </p>
        </div>
        <div className="kx-cms__head-actions">
          <Button variant="secondary" onClick={createDraft} disabled={busy} leadingIcon={<IconPlus size={16} />}>
            새 콘텐츠
          </Button>
        </div>
      </header>

      {error && (
        <div className="kx-cms-alert" role="alert">
          <IconWarning size={14} /> {error}
        </div>
      )}

      <div className="kx-cms-grid">
        {/* 좌: 콘텐츠 목록 */}
        <section className="kx-card kx-cms-col" aria-label="콘텐츠 목록">
          {loading ? (
            <div className="kx-cms-empty">불러오는 중…</div>
          ) : items.length === 0 ? (
            <div className="kx-cms-empty">콘텐츠가 없습니다. “새 콘텐츠”로 초안을 만드세요.</div>
          ) : (
            <ul className="kx-cms-list">
              {items.map((c) => {
                const m = STATUS_META[c.status];
                return (
                  <li key={c.id}>
                    <button
                      className={`kx-cms-list__item ${c.id === selectedId ? 'is-active' : ''}`}
                      onClick={() => setSelectedId(c.id)}
                      aria-current={c.id === selectedId}
                    >
                      <span className="kx-cms-list__label">
                        <IconDocument size={18} />
                        <span className="kx-cms-list__name">{c.title}</span>
                      </span>
                      <span className={`kx-cms-pill ${m.cls}`}>{m.label}</span>
                    </button>
                  </li>
                );
              })}
            </ul>
          )}
        </section>

        {/* 중: 에디터 */}
        <section className="kx-card kx-cms-col kx-cms-editor" aria-label="콘텐츠 에디터">
          <input
            className="kx-cms-title-input"
            defaultValue={selected?.title ?? ''}
            aria-label="제목"
            key={selected?.id ?? 'none'}
            placeholder="콘텐츠 제목"
          />

          <div className="kx-cms-toolbar" role="toolbar" aria-label="서식">
            {TOOLS.map((t) => (
              <button key={t.title} className="kx-icon-btn" title={t.title} aria-label={t.title}>
                <ToolIcon d={t.d} />
              </button>
            ))}
            <span className="kx-cms-toolbar__divider" aria-hidden="true" />
            <button className="kx-icon-btn" title="이미지 삽입" aria-label="이미지 삽입">
              <IconImage size={18} />
            </button>
            <button className="kx-icon-btn" title="버튼 블록" aria-label="버튼 블록">
              <IconPlus size={18} />
            </button>
          </div>

          <div>
            <div className="kx-cms-sublabel" style={{ marginBottom: 8 }}>
              미디어 라이브러리
            </div>
            <div className="kx-cms-media">
              <div className="kx-cms-media__thumb">
                <IconImage size={22} />
              </div>
              <div className="kx-cms-media__thumb">
                <IconImage size={22} />
              </div>
              <button className="kx-cms-media__add" title="이미지 추가" aria-label="이미지 추가">
                <IconPlus size={20} />
              </button>
            </div>
          </div>

          <div className="kx-cms-blocks">
            <div className="kx-cms-block">
              <div className="kx-cms-block__head">
                <span className="kx-cms-block__kind">본문</span>
              </div>
              <p className="kx-cms-block__body">
                {selected?.body || '본문 블록을 편집하세요. 텍스트·이미지·버튼·AI 요약 블록을 조합할 수 있습니다.'}
              </p>
            </div>
            <div className="kx-cms-block kx-cms-block--ai">
              <div className="kx-cms-block__head">
                <AiLabel>AI 요약 정보</AiLabel>
                <span className="kx-cms-disabled-hint" title="AI 요약 자동 생성은 아직 배선되지 않았습니다(AiTextRouter 연동 예정).">
                  미배선
                </span>
              </div>
              <p className="kx-cms-block__body">
                AI 요약 블록은 AiTextRouter(Claude) 연동 후 자동 생성됩니다.
              </p>
            </div>
          </div>

          <div>
            <div className="kx-cms-sublabel" style={{ marginBottom: 8, display: 'flex', alignItems: 'center', gap: 8 }}>
              예약 게시
              {selected?.scheduledAt && selected.status !== 'published' && (
                <span className="kx-cms-pill kx-cms-pill--scheduled">예약됨</span>
              )}
            </div>
            <div className="kx-cms-sched">
              <IconCalendar size={18} />
              <input
                type="datetime-local"
                className="kx-cms-sched__input"
                value={schedInput}
                onChange={(e) => setSchedInput(e.target.value)}
                aria-label="예약 게시 시각"
                disabled={!selected || schedSaving}
              />
              <Button variant="secondary" onClick={saveSchedule} disabled={!selected || schedSaving}>
                {schedSaving ? '저장 중…' : '예약 저장'}
              </Button>
            </div>
            <div className="kx-cms-sched__hint">
              {selected?.scheduledAt
                ? `예약: ${fmtDate(selected.scheduledAt)} — 승인(approved) 상태이면 시각 도달 시 자동 게시됩니다.`
                : '시각을 지정하면, 승인 후 예약 시각에 자동 게시됩니다. 비우고 저장하면 예약이 해제됩니다.'}
            </div>
          </div>
        </section>

        {/* 우: 워크플로 */}
        <aside className="kx-card kx-cms-flow" aria-label="게시 워크플로">
          <div className="kx-cms-flow__section">
            <span className="kx-cms-flow__label">게시 워크플로</span>
            <div className="kx-cms-stepper" aria-label="게시 단계">
              {FLOW_ORDER.map((s, i) => (
                <div
                  key={s}
                  className={`kx-cms-step ${i < curIdx ? 'is-done' : ''} ${i === curIdx ? 'is-current' : ''}`}
                >
                  <span className="kx-cms-step__dot">
                    {i < curIdx && <IconCheckCircle size={12} />}
                  </span>
                  {STATUS_META[s].label}
                </div>
              ))}
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 8 }}>
              {selected?.status === 'draft' && (
                <Button block variant="secondary" onClick={() => advance('review')} disabled={busy}>
                  검수 요청
                </Button>
              )}
              {selected?.status === 'review' && (
                <Button block onClick={() => advance('approved')} disabled={busy} leadingIcon={<IconCheckCircle size={16} />}>
                  검수 승인
                </Button>
              )}
              {selected?.status === 'approved' && (
                <Button block onClick={() => advance('published')} disabled={busy} leadingIcon={<IconSpark size={16} />}>
                  최종 게시
                </Button>
              )}
              {selected?.status === 'published' && (
                <div className="kx-cms-terminal">
                  <IconCheckCircle size={14} /> 게시 완료됨 — 새 버전은 “새 콘텐츠”로 작성
                </div>
              )}
            </div>
          </div>

          <div className="kx-cms-schedcard">
            <div className="kx-cms-schedcard__t">
              <IconCalendar size={14} /> 콘텐츠 정보
            </div>
            <div style={{ fontSize: 13, color: 'var(--color-neutral-700)' }}>
              최근 수정 {fmtDate(selected?.updatedAt ?? null)}
              {selected?.authorName ? ` · ${selected.authorName}` : ''}
            </div>
          </div>

          <div className="kx-cms-flow__toggles">
            <label className="kx-toggle">
              <span>현장 사이니지 동시 배포</span>
              <input type="checkbox" checked={signage} onChange={(e) => setSignage(e.target.checked)} />
              <span className="kx-toggle__track" aria-hidden="true" />
            </label>
            <label className="kx-toggle">
              <span>메일링 리스트 통보</span>
              <input type="checkbox" checked={mailing} onChange={(e) => setMailing(e.target.checked)} />
              <span className="kx-toggle__track" aria-hidden="true" />
            </label>
          </div>
        </aside>
      </div>
    </div>
  );
}
