import { useMemo, useState } from 'react';
import { useQuery } 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 { KxDataTable, type KxColumn } from '../../components/KxDataTable';
import { IconClock, IconDownload, IconSpark } from '../../components/ui/icons';
import { ApiRequestError } from '../../api/client';
import { useResolvedEventId } from '../../hooks/useResolvedEventId';
import { useParams } from 'react-router-dom';
import { LEADS } from './sampleVisitor';
import { visitorApi, type LeadItemDto } from './visitorApi';
import './visitor.css';

/*
 * SCR-32 리드 관리·AI 스코어링 (M10). Stitch scr_32_lead_scoring 이식.
 * 정상 경로: GET /api/events/{eventId}/leads?boothId (마스킹 목록 + AI 저장 스코어).
 * KPI 는 로드된 리드에서 파생(핫리드=스코어 80+, 전환 추정=AI 파생). 폴백: 오프라인 강등 시 sampleVisitor.LEADS.
 * ★ 보안 불변: 리드 이름·연락처·이메일은 서버 마스킹 필드만 소비(PII 동의·보존 R10).
 */
export function LeadScoringPage() {
  const eventId = useResolvedEventId();
  const { boothId } = useParams();
  const [hotOnly, setHotOnly] = useState(false);
  const [selectedId, setSelectedId] = useState<string>('');
  const [exporting, setExporting] = useState(false);
  const [exportError, setExportError] = useState<string | null>(null);
  const [rescoringId, setRescoringId] = useState<string | null>(null);
  const [rescoreNote, setRescoreNote] = useState<string | null>(null);

  const handleExport = async () => {
    if (!eventId || exporting) return;
    setExporting(true);
    setExportError(null);
    try {
      await visitorApi.exportLeadsCsv(eventId, boothId ?? null);
    } catch {
      setExportError('CSV 내보내기에 실패했습니다. 잠시 후 다시 시도해 주세요.');
    } finally {
      setExporting(false);
    }
  };

  const q = useQuery({
    queryKey: ['leads', eventId, boothId ?? null],
    queryFn: () => visitorApi.leads(eventId as string, boothId ?? null, 0, 100),
    enabled: !!eventId,
    retry: false,
  });

  const handleRescore = async (leadId: string) => {
    if (!eventId || rescoringId) return;
    setRescoringId(leadId);
    setRescoreNote(null);
    try {
      const r = await visitorApi.rescoreLead(eventId, leadId);
      setRescoreNote(
        r.degraded
          ? 'AI 미가용 — 기존 규칙 스코어 유지'
          : `AI 재계산 완료 · ${r.provider}`,
      );
      await q.refetch();
    } catch {
      setRescoreNote('AI 재계산에 실패했습니다. 잠시 후 다시 시도해 주세요.');
    } finally {
      setRescoringId(null);
    }
  };

  const degraded = isDegradable(q.error);
  const leads: LeadItemDto[] = q.data?.items ?? (degraded ? SAMPLE_LEADS : []);
  const total = q.data?.total ?? (degraded ? SAMPLE_LEADS.length : 0);
  const hardError = q.isError && !degraded;

  const rows = useMemo(
    () => (hotOnly ? leads.filter((l) => l.score >= 80) : leads),
    [hotOnly, leads],
  );
  const selected = leads.find((l) => l.id === selectedId) ?? rows[0] ?? leads[0] ?? null;

  const columns = useMemo<KxColumn<LeadItemDto>[]>(
    () => [
      { key: 'name', header: '이름', value: (l) => l.nameMasked,
        render: (l) => <span className="kx-vis__lead-name">{l.nameMasked}</span> },
      { key: 'company', header: '소속', value: (l) => l.company ?? '', render: (l) => l.company ?? '-' },
      { key: 'product', header: '관심 제품', value: (l) => l.product ?? '', render: (l) => l.product ?? '-' },
      { key: 'interest', header: '관심도', numeric: true, value: (l) => l.interest,
        render: (l) => <Stars value={l.interest} /> },
      { key: 'score', header: 'AI 스코어', numeric: true, value: (l) => l.score,
        render: (l) => <ScoreGauge score={l.score} /> },
      { key: 'collectedAt', header: '수집시각', value: (l) => l.collectedAt ?? '',
        render: (l) => <span className="tnum">{l.collectedAt ?? '-'}</span> },
    ],
    [],
  );

  const hotCount = leads.filter((l) => l.score >= 80).length;
  const kpis = [
    { label: '총 리드', value: total.toLocaleString(), sub: undefined as string | undefined, ai: false },
    { label: '핫리드', value: String(hotCount), sub: 'AI 스코어 80+', ai: false },
    { label: '팔로업 대기', value: String(Math.max(total - hotCount, 0)), sub: undefined, ai: false },
    { label: '전환 추정', value: String(Math.round(hotCount * 0.35)), sub: 'AI 파생', ai: true },
  ];

  return (
    <div className="kx-vis">
      <header className="kx-vis__head">
        <div>
          <h1 className="kx-vis__title">리드 관리 · AI 스코어링</h1>
          <p className="kx-vis__subtitle">부스 방문 리드 수집 · 스코어링 · 후속</p>
        </div>
        <div className="kx-vis__head-actions">
          {degraded && (
            <span className="kx-vis__degraded" title="리드 API 미연결 — 시연 데이터">오프라인 — 샘플</span>
          )}
          {exportError && (
            <span className="kx-vis__degraded" role="alert">{exportError}</span>
          )}
          <Button
            variant="secondary"
            leadingIcon={<IconDownload size={16} />}
            onClick={handleExport}
            disabled={exporting || degraded}
          >
            {exporting ? '내보내는 중…' : 'CSV 내보내기'}
          </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-vis__kpis kx-vis__kpis--4" aria-label="리드 핵심 지표">
            {kpis.map((k) => (
              <div key={k.label} className={`kx-kpi ${k.ai ? 'kx-kpi--ai' : ''}`}>
                <span className="kx-kpi__label">
                  {k.label}
                  {k.ai && (
                    <span className="kx-kpi__ai" aria-hidden="true">
                      <IconSpark size={12} />
                    </span>
                  )}
                </span>
                <strong className="kx-kpi__value tnum">{k.value}</strong>
                {k.sub && <span className="kx-kpi__sub">{k.sub}</span>}
              </div>
            ))}
          </section>

          <div className="kx-vis__lead-split">
            {/* 리드 테이블 */}
            <section className="kx-card kx-vis__lead-table-card" aria-label="리드 목록">
              <KxDataTable
                columns={columns}
                rows={rows}
                rowKey={(l) => l.id}
                onRowClick={(l) => setSelectedId(l.id)}
                isRowSelected={(l) => l.id === selected?.id}
                rowClassName={() => 'kx-vis__lead-row'}
                zebra={false}
                searchPlaceholder="이름·소속·제품 검색"
                ariaLabel="리드 목록"
                emptyTitle="수집된 리드가 없습니다"
                emptyDescription="부스 배지 QR 스캔이 수집되면 표시됩니다."
                toolbarStart={
                  <div className="kx-vis__filters" role="group" aria-label="리드 필터">
                    <span className="kx-vis__filters-label">필터</span>
                    <button
                      type="button"
                      className={`kx-chip ${hotOnly ? 'is-active' : ''}`}
                      aria-pressed={hotOnly}
                      onClick={() => setHotOnly((v) => !v)}
                    >
                      스코어 80+ {hotOnly && <span aria-hidden="true">×</span>}
                    </button>
                  </div>
                }
              />
            </section>

            {/* 리드 상세·팔로업 */}
            {selected && (
              <LeadDetail
                lead={selected}
                onExport={handleExport}
                exporting={exporting}
                onRescore={handleRescore}
                rescoring={rescoringId === selected.id}
                canRescore={!degraded}
                rescoreNote={rescoreNote}
              />
            )}
          </div>
        </>
      )}
    </div>
  );
}

function LeadDetail({
  lead,
  onExport,
  exporting,
  onRescore,
  rescoring,
  canRescore,
  rescoreNote,
}: {
  lead: LeadItemDto;
  onExport: () => void;
  exporting: boolean;
  onRescore: (leadId: string) => void;
  rescoring: boolean;
  canRescore: boolean;
  rescoreNote: string | null;
}) {
  const hot = lead.score >= 80;
  return (
    <aside className="kx-vis__lead-detail" aria-label="리드 상세">
      <div className="kx-card">
        <div className="kx-vis__lead-profile">
          <span className="kx-vis__avatar kx-vis__avatar--lg" aria-hidden="true">
            {lead.nameMasked.charAt(0)}
          </span>
          <div>
            <div className="kx-vis__lead-profile-top">
              <h2>{lead.nameMasked}</h2>
              {hot && <span className="kx-vis__hot">HOT</span>}
            </div>
            <p className="kx-vis__lead-role">{lead.role ?? '-'} · {lead.company ?? '-'}</p>
            <p className="kx-vis__lead-contact">
              {lead.phoneMasked ?? '-'} · {lead.emailMasked ?? '-'}
            </p>
          </div>
        </div>

        {/* AI 스코어 분석 */}
        <div className="kx-vis__ai-card">
          <div className="kx-vis__ai-card-head">
            <span className="kx-vis__ai-card-title">
              <AiLabel>AI 스코어 분석</AiLabel>
            </span>
            <span className="kx-vis__ai-score tnum">{lead.score}</span>
          </div>
          <div className="kx-vis__ai-actions">
            <Button
              variant="ai"
              leadingIcon={<IconSpark size={14} />}
              onClick={() => onRescore(lead.id)}
              disabled={rescoring || !canRescore}
              title={canRescore ? 'AI로 리드 스코어를 재계산합니다' : '오프라인(샘플) 상태에서는 재계산할 수 없습니다'}
            >
              {rescoring ? 'AI 재계산 중…' : 'AI 재계산'}
            </Button>
            {rescoreNote && (
              <span className="kx-vis__ai-note" role="status">{rescoreNote}</span>
            )}
            {!lead.aiGenerated && (
              <span className="kx-vis__ai-note" title="AI 미생성 — 규칙 기반 스코어">규칙 기반</span>
            )}
          </div>
          <ul className="kx-vis__ai-reasons">
            {lead.aiReasons.map((r, i) => (
              <li key={i}>
                <span className="kx-vis__ai-check" aria-hidden="true">
                  <CheckGlyph />
                </span>
                {r}
              </li>
            ))}
          </ul>
        </div>

        {/* AI 추천 팔로업 */}
        <div className="kx-vis__followup">
          <label className="kx-vis__followup-label" htmlFor="kx-followup">
            <IconSpark size={14} /> AI 추천 팔로업 메시지
          </label>
          <textarea id="kx-followup" className="kx-vis__followup-input" defaultValue={lead.followupDraft ?? ''} rows={7} />
        </div>

        <div className="kx-vis__lead-actions">
          <Button block>EDM 발송하기</Button>
          <div className="kx-vis__lead-actions-row">
            <Button variant="secondary" leadingIcon={<IconDownload size={16} />} onClick={onExport} disabled={exporting}>
              {exporting ? '내보내는 중…' : 'CSV 내보내기'}
            </Button>
            <Button variant="secondary">노트 기록</Button>
          </div>
        </div>
      </div>

      <div className="kx-card">
        <div className="kx-card__head">
          <h2><IconClock className="kx-title-ic" size={18} />최근 활동 로그</h2>
        </div>
        <ul className="kx-vis__activity">
          {lead.activity.map((a, i) => (
            <li key={i}>
              <span className="kx-dot" />
              <span className="kx-vis__activity-text">{a.text}</span>
              <span className="kx-vis__activity-at">{a.at}</span>
            </li>
          ))}
          {lead.activity.length === 0 && <li className="kx-vis__activity-empty">활동 로그 없음</li>}
        </ul>
      </div>
    </aside>
  );
}

/** 관심도 별점(1~5, 선 SVG). */
function Stars({ value }: { value: number }) {
  return (
    <span className="kx-stars" role="img" aria-label={`관심도 ${value}점 / 5점`}>
      {[1, 2, 3, 4, 5].map((n) => (
        <StarGlyph key={n} filled={n <= value} />
      ))}
    </span>
  );
}
function StarGlyph({ filled }: { filled: boolean }) {
  return (
    <svg width={16} height={16} viewBox="0 0 24 24" fill={filled ? 'currentColor' : 'none'} stroke="currentColor" strokeWidth={filled ? 0 : 1.6} className={filled ? 'is-filled' : 'is-empty'} aria-hidden="true">
      <path d="M12 3l2.6 5.9 6.4.6-4.8 4.3 1.4 6.3L12 17.8 6.4 20.4l1.4-6.3L3 9.8l6.4-.6L12 3z" />
    </svg>
  );
}

/** 체크 글리프(선 SVG) — AI 근거 목록 마커(글리프 텍스트 ✓ 대체, QA 지적). */
function CheckGlyph() {
  return (
    <svg width={14} height={14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2.4} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M4 12l5 5L20 6" />
    </svg>
  );
}

/** AI 스코어 게이지(0~100). 80+ 는 AI 액센트(보라). */
function ScoreGauge({ score }: { score: number }) {
  const hot = score >= 80;
  return (
    <span className="kx-gauge">
      <span className="kx-gauge__track">
        <span className={`kx-gauge__fill ${hot ? 'is-hot' : ''}`} style={{ width: `${score}%` }} />
      </span>
      <span className={`kx-gauge__num tnum ${hot ? 'is-hot' : ''}`}>{score}</span>
    </span>
  );
}

/** 폴백 리드(오프라인 강등 시) — sampleVisitor.LEADS 파생(마스킹 유지). */
const SAMPLE_LEADS: LeadItemDto[] = LEADS.map((l) => ({
  id: l.id,
  nameMasked: l.nameMasked,
  role: l.role,
  company: l.company,
  product: l.product,
  interest: l.interest,
  score: l.score,
  collectedAt: l.collectedAt,
  phoneMasked: l.phoneMasked,
  emailMasked: l.emailMasked,
  aiReasons: l.aiReasons,
  activity: l.activity,
  followupDraft: l.followupDraft,
  aiGenerated: true,
}));

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