import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { AiLabel } from '../../components/ui/Badge';
import { Button } from '../../components/ui/Button';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { IconImage, IconMail, IconPlus, IconSpark } from '../../components/ui/icons';
import { ApiRequestError } from '../../api/client';
import { useResolvedEventId } from '../../hooks/useResolvedEventId';
import { CAMPAIGN_STATUS_LABEL, CAMPAIGNS, SEGMENTS, type CampaignStatus } from './sampleMarketing';
import { marketingApi, type CampaignDto } from './marketingApi';
import './marketing.css';

/*
 * SCR-33 EDM·캠페인 관리 (M12). Stitch scr_33_edm_campaign 이식.
 * 정상 경로: GET /api/events/{eventId}/campaigns (목록) · POST /campaigns (생성 — 발송 미구현, status 전이만).
 * KPI 는 캠페인 목록에서 파생. 폴백: 오프라인 강등 시 sampleMarketing.CAMPAIGNS.
 * ★ 정보통신망법 수신동의·수신거부 준수 표기 상시 노출. 세그먼트 규모는 집계 힌트(관람객 PII 미포함).
 */
export function EdmCampaignPage() {
  const { t } = useTranslation();
  const eventId = useResolvedEventId();
  const queryClient = useQueryClient();
  const [filter, setFilter] = useState<'all' | 'active' | 'done'>('all');
  const [segments, setSegments] = useState<Record<string, boolean>>(
    Object.fromEntries(SEGMENTS.map((s) => [s.id, s.defaultOn])),
  );
  const [schedule, setSchedule] = useState<'now' | 'later'>('now');
  const [name, setName] = useState('');
  const [scheduledAt, setScheduledAt] = useState('');

  const q = useQuery({
    queryKey: ['campaigns', eventId],
    queryFn: () => marketingApi.campaigns(eventId as string),
    enabled: !!eventId,
    retry: false,
  });

  const degraded = isDegradable(q.error);
  const campaigns: CampaignDto[] = q.data ?? (degraded ? SAMPLE_CAMPAIGNS : []);
  const hardError = q.isError && !degraded;

  const createMut = useMutation({
    mutationFn: (body: Parameters<typeof marketingApi.createCampaign>[1]) =>
      marketingApi.createCampaign(eventId as string, body),
    onSuccess: () => {
      setName('');
      setScheduledAt('');
      queryClient.invalidateQueries({ queryKey: ['campaigns', eventId] });
    },
  });

  const [sendMsg, setSendMsg] = useState<string | null>(null);
  const sendMut = useMutation({
    // 안전 기본: 테스트 모드(live=false). 운영 실발송은 ①UI 이중 확인(live=true) ②서버 EDM_TEST_MODE=false 둘 다 필요.
    mutationFn: (vars: { id: string; live: boolean }) =>
      marketingApi.sendCampaign(eventId as string, vars.id, vars.live),
    onSuccess: (res) => {
      const n = res.sentCount.toLocaleString();
      let base: string;
      if (res.testMode) {
        // 신규 키(g04_i18n_todo) — 미번역 시 defaultValue 로 우아하게 폴백.
        base = t('marketing.sentTest', {
          defaultValue: '테스트 발송: 대상 {{eligible}}명 · 실발송 {{n}}건 (실 수신자 미발송)',
          n,
          eligible: res.eligible.toLocaleString(),
        });
      } else if (res.mailEnabled) {
        base = t('marketing.sentDone', { n });
      } else {
        base = t('marketing.sentDisabled', { n });
      }
      const extra =
        res.skipped > 0
          ? ' · ' +
            t('marketing.skipped', {
              defaultValue: '보류 {{n}}건',
              n: res.skipped.toLocaleString(),
            })
          : '';
      setSendMsg(base + extra);
      queryClient.invalidateQueries({ queryKey: ['campaigns', eventId] });
    },
    onError: () => setSendMsg(t('marketing.sendFail')),
  });

  function confirmSend(c: CampaignDto) {
    if (sendMut.isPending) return;
    const ok = window.confirm(t('marketing.confirm', { name: c.name }));
    if (ok) {
      setSendMsg(null);
      sendMut.mutate({ id: c.id, live: false });
    }
  }

  /** 운영 실발송 — 이중 확인(경고 confirm + 'LIVE' 타이핑). 서버 EDM_TEST_MODE=false 일 때만 실제 발송된다. */
  function confirmSendLive(c: CampaignDto) {
    if (sendMut.isPending) return;
    const ok = window.confirm(
      t('marketing.confirmLive', { name: c.name, audience: c.audience.toLocaleString() }),
    );
    if (!ok) return;
    const typed = window.prompt(t('marketing.confirmLiveType'));
    if (typed !== 'LIVE') return;
    setSendMsg(null);
    sendMut.mutate({ id: c.id, live: true });
  }

  const audience = useMemo(
    () => SEGMENTS.filter((s) => segments[s.id]).reduce((sum, s) => sum + s.count, 0),
    [segments],
  );

  const rows = campaigns.filter((c) =>
    filter === 'all'
      ? true
      : filter === 'done'
        ? c.status === 'done'
        : c.status === 'scheduled' || c.status === 'sending',
  );

  const kpis = [
    { label: '전체 캠페인', value: String(campaigns.length), unit: '개', tone: 'primary' as const },
    { label: '진행중', value: String(campaigns.filter((c) => c.status === 'scheduled' || c.status === 'sending').length), unit: '개', tone: 'ai' as const },
    { label: '완료', value: String(campaigns.filter((c) => c.status === 'done').length), unit: '개', tone: 'success' as const },
    { label: '초안', value: String(campaigns.filter((c) => c.status === 'draft').length), unit: '개', tone: 'warning' as const },
  ];

  const canCreate = !!eventId && name.trim().length > 0 && !createMut.isPending;
  function submitCampaign() {
    if (!canCreate) return;
    createMut.mutate({
      name: name.trim(),
      audience,
      scheduleType: schedule,
      scheduledAt: schedule === 'later' ? scheduledAt : undefined,
    });
  }

  return (
    <div className="kx-mkt">
      <header className="kx-mkt__head">
        <div>
          <h1 className="kx-mkt__title">EDM · 캠페인 관리</h1>
          <p className="kx-mkt__subtitle">세그먼트 발송 · 성과 추적 · AI 카피 최적화</p>
        </div>
        <div className="kx-mkt__head-actions">
          {degraded && (
            <span className="kx-vis__degraded" title="캠페인 API 미연결 — 시연 데이터">오프라인 — 샘플</span>
          )}
          <Button leadingIcon={<IconPlus size={16} />} onClick={submitCampaign} disabled={!canCreate}>
            새 캠페인
          </Button>
        </div>
      </header>

      {!eventId && (
        <EmptyState title="행사를 선택해 주세요" description="캠페인을 조회할 행사가 지정되지 않았습니다." />
      )}

      {eventId && q.isLoading && !degraded && (
        <div style={{ display: 'grid', gap: 16 }}>
          <Skeleton height={92} radius={12} />
          <Skeleton height={420} radius={12} />
        </div>
      )}

      {hardError && <ErrorState message="캠페인을 불러오지 못했습니다." onRetry={() => q.refetch()} />}

      {eventId && (!q.isLoading || degraded) && !hardError && (
        <>
          <section className="kx-mkt__kpis" aria-label="캠페인 핵심 지표">
            {kpis.map((k) => (
              <div key={k.label} className={`kx-kpi kx-kpi--accent-${k.tone}`}>
                <span className="kx-kpi__label">{k.label}</span>
                <strong className="kx-kpi__value tnum">
                  {k.value}
                  {k.unit && <span className="kx-kpi__unit">{k.unit}</span>}
                </strong>
              </div>
            ))}
          </section>

          {createMut.isError && (
            <div className="kx-vis__degraded" role="alert" style={{ marginBottom: 12 }}>
              캠페인 생성에 실패했습니다. 권한 또는 입력값을 확인해 주세요.
            </div>
          )}

          {sendMsg && (
            <div className="kx-mkt__send-msg" role="status" style={{ marginBottom: 12 }}>
              {sendMsg}
            </div>
          )}

          <div className="kx-mkt__split">
            {/* 캠페인 리스트 */}
            <section className="kx-mkt__list-col" aria-label="캠페인 목록">
              <div className="kx-mkt__list-head">
                <h2>캠페인 목록</h2>
                <div className="kx-mkt__tabs" role="tablist" aria-label="상태 필터">
                  {(['all', 'active', 'done'] as const).map((t) => (
                    <button
                      key={t}
                      role="tab"
                      aria-selected={filter === t}
                      className={`kx-chip ${filter === t ? 'is-active' : ''}`}
                      onClick={() => setFilter(t)}
                    >
                      {t === 'all' ? '전체' : t === 'active' ? '진행중' : '완료'}
                    </button>
                  ))}
                </div>
              </div>
              <ul className="kx-mkt__campaigns">
                {rows.map((c) => (
                  <CampaignRow
                    key={c.id}
                    campaign={c}
                    onSend={() => confirmSend(c)}
                    onSendLive={() => confirmSendLive(c)}
                    sending={sendMut.isPending && sendMut.variables?.id === c.id}
                  />
                ))}
                {rows.length === 0 && (
                  <li>
                    <EmptyState title="캠페인이 없습니다" description="우측 빌더에서 새 캠페인을 생성하세요." />
                  </li>
                )}
              </ul>
            </section>

            {/* 캠페인 빌더 */}
            <aside className="kx-mkt__builder" aria-label="캠페인 빌더">
              <div className="kx-card">
                <div className="kx-card__head">
                  <h2><IconMail className="kx-title-ic" size={18} />캠페인 빌더</h2>
                  <AiLabel>AI 최적화</AiLabel>
                </div>

                <p className="kx-mkt__field-label">캠페인 이름</p>
                <input
                  type="text"
                  className="kx-mkt__datetime"
                  aria-label="캠페인 이름"
                  placeholder="예: 2026 스마트팩토리 사전등록 안내"
                  value={name}
                  onChange={(e) => setName(e.target.value)}
                />

                <p className="kx-mkt__field-label">대상 세그먼트</p>
                <div className="kx-mkt__segments">
                  {SEGMENTS.map((s) => (
                    <label key={s.id} className="kx-mkt__segment">
                      <input
                        type="checkbox"
                        checked={!!segments[s.id]}
                        onChange={(e) => setSegments((prev) => ({ ...prev, [s.id]: e.target.checked }))}
                      />
                      <span>{s.label}</span>
                      <span className="kx-mkt__segment-count tnum">{s.count.toLocaleString()}명</span>
                    </label>
                  ))}
                </div>
                <p className="kx-mkt__field-label">대상 규모: <strong className="tnum">{audience.toLocaleString()}명</strong> (수신동의자 한정)</p>

                <div className="kx-mkt__ai-box">
                  <div className="kx-mkt__ai-box-head">
                    <span>AI 최적화</span>
                    <IconSpark size={16} />
                  </div>
                  <p>세그먼트 성향을 분석해 오픈율이 가장 높을 카피와 발송 시간을 제안합니다.</p>
                  <Button variant="ai" block leadingIcon={<IconSpark size={16} />}>
                    AI 카피 초안 생성
                  </Button>
                </div>

                <p className="kx-mkt__field-label">메인 이미지 에셋</p>
                <button type="button" className="kx-mkt__image-slot">
                  <IconImage size={28} />
                  <span>나노바나나 예상 이미지 삽입</span>
                </button>

                <p className="kx-mkt__field-label">발송 설정</p>
                <div className="kx-mkt__schedule">
                  <div className="kx-seg" role="tablist" aria-label="발송 시점">
                    <button
                      role="tab"
                      aria-selected={schedule === 'now'}
                      className={`kx-seg__btn ${schedule === 'now' ? 'is-active' : ''}`}
                      onClick={() => setSchedule('now')}
                    >
                      즉시 발송
                    </button>
                    <button
                      role="tab"
                      aria-selected={schedule === 'later'}
                      className={`kx-seg__btn ${schedule === 'later' ? 'is-active' : ''}`}
                      onClick={() => setSchedule('later')}
                    >
                      예약 발송
                    </button>
                  </div>
                  {schedule === 'later' && (
                    <input
                      type="datetime-local"
                      className="kx-mkt__datetime"
                      aria-label="예약 발송 일시"
                      value={scheduledAt}
                      onChange={(e) => setScheduledAt(e.target.value)}
                    />
                  )}
                </div>

                <div className="kx-mkt__preview">
                  <div className="kx-mkt__preview-head">미리보기</div>
                  <div className="kx-mkt__preview-body">
                    <div className="kx-mkt__preview-banner">메인 배너 이미지 영역</div>
                    <p className="kx-mkt__preview-title">{name.trim() || '2026 KINTEX 스마트팩토리 엑스포에 초대합니다'}</p>
                    <p className="kx-mkt__preview-text">
                      안녕하세요, 고객님. KINTEX가 제안하는 미래 제조 혁신의 현장으로 귀하를 정중히 모십니다.
                    </p>
                    <footer className="kx-mkt__preview-foot">
                      <p>본 메일은 수신동의를 하신 고객님께 발송되었습니다.</p>
                      <span className="kx-mkt__preview-links">
                        <a href="#unsubscribe" onClick={(e) => e.preventDefault()}>수신거부</a>
                        <span>정보통신망법 수신동의 준수</span>
                      </span>
                    </footer>
                  </div>
                </div>

                <Button block onClick={submitCampaign} disabled={!canCreate}>
                  {createMut.isPending ? '생성 중…' : schedule === 'later' ? '예약 캠페인 등록' : '캠페인 초안 저장'}
                </Button>
                <p className="kx-vis__ai-note" style={{ marginTop: 8 }}>
                  발송 버튼은 기본 테스트 모드로 동작합니다(실 수신자 미발송·수신동의자만 집계). 운영 실발송은 서버 정책에 따라 개방됩니다.
                </p>
              </div>
            </aside>
          </div>
        </>
      )}
    </div>
  );
}

function CampaignRow({
  campaign: c,
  onSend,
  onSendLive,
  sending,
}: {
  campaign: CampaignDto;
  onSend?: () => void;
  onSendLive?: () => void;
  sending?: boolean;
}) {
  const { t } = useTranslation();
  const status = normalizeStatus(c.status);
  // 발송 가능 상태 = 초안·예약(발송중·완료는 불가). 봉인/중복 발송 방지는 서버가 최종 강제.
  const canSend = status === 'draft' || status === 'scheduled';
  return (
    <li className="kx-mkt__campaign">
      <div className="kx-mkt__campaign-main">
        <span className={`kx-mkt__campaign-icon is-${status}`} aria-hidden="true">
          <StatusGlyph status={status} />
        </span>
        <div className="kx-mkt__campaign-info">
          <div className="kx-mkt__campaign-top">
            <span className={`kx-mkt__cpill is-${status}`}>{CAMPAIGN_STATUS_LABEL[status]}</span>
            <h3>{c.name}</h3>
          </div>
          <div className="kx-mkt__campaign-meta">
            <span>대상: {c.audience.toLocaleString()}명</span>
            <span className="kx-mkt__dot-sep" aria-hidden="true" />
            <span>{c.meta ?? '-'}</span>
          </div>
        </div>
      </div>
      <div className="kx-mkt__campaign-metrics">
        <div>
          <span className="kx-mkt__metric-k">오픈율</span>
          <strong>{c.openRate ?? '-'}</strong>
        </div>
        <div>
          <span className="kx-mkt__metric-k">클릭율</span>
          <strong>{c.clickRate ?? '-'}</strong>
        </div>
        {canSend && onSend && (
          <Button variant="secondary" onClick={onSend} disabled={sending}>
            {sending ? t('marketing.sending') : t('marketing.sendTestBtn')}
          </Button>
        )}
        {canSend && onSendLive && (
          <Button variant="primary" onClick={onSendLive} disabled={sending}>
            {t('marketing.sendLiveBtn')}
          </Button>
        )}
      </div>
    </li>
  );
}

const KNOWN_STATUS: CampaignStatus[] = ['draft', 'scheduled', 'sending', 'done'];
function normalizeStatus(s: string): CampaignStatus {
  return (KNOWN_STATUS as string[]).includes(s) ? (s as CampaignStatus) : 'draft';
}

function StatusGlyph({ status }: { status: CampaignStatus }) {
  const common = { fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
  return (
    <svg width={20} height={20} viewBox="0 0 24 24" aria-hidden="true">
      {status === 'scheduled' ? (
        <>
          <circle cx="12" cy="12" r="9" {...common} />
          <path d="M12 7v5l3 2" {...common} />
        </>
      ) : status === 'done' ? (
        <path d="M4 12l5 5L20 6" {...common} />
      ) : (
        <>
          <path d="M4 6h16v12H4z" {...common} />
          <path d="M4 7l8 6 8-6" {...common} />
        </>
      )}
    </svg>
  );
}

/** 폴백 캠페인(오프라인 강등 시) — sampleMarketing.CAMPAIGNS 파생. */
const SAMPLE_CAMPAIGNS: CampaignDto[] = CAMPAIGNS.map((c) => ({
  id: c.id,
  name: c.name,
  status: c.status,
  audience: c.audience,
  meta: c.meta,
  openRate: c.openRate,
  clickRate: c.clickRate,
}));

function isDegradable(error: unknown): boolean {
  return (
    error instanceof ApiRequestError &&
    (error.code === 'NETWORK' || error.code === 'NOT_FOUND' || error.code === 'NOT_IMPLEMENTED')
  );
}
