/*
 * SCR-45 회의록 (meeting). 참조: UIWS meeting/MeetingDetailPage.
 * 좌: 회의 목록 / 우: 상세(본문·회의록 편집·액션아이템).
 * 백엔드: /api/work/meetings (get·create·minutes·actions·action status).
 * STT 전사·AI 회의록 자동작성은 실배선(G-06 해소, 2026-07-14) — MeetingAiPanel(업로드→STT→회의록)
 *   ↔ MeetingController/MeetingSttClient/MeetingMinutesGenerator + V52 meeting_transcript. Jasper PDF는 후속.
 */
import { useEffect, useRef, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { meetingApi } from '../../api/endpoints';
import type { MeetingSaveRequest } from '../../api/types';
import { AiLabel } from '../../components/ui/Badge';
import { Button } from '../../components/ui/Button';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { IconDownload, IconPlus, IconSpark, IconUpload } from '../../components/ui/icons';
import { StatusPill, errMessage, fmtDateTime, useToast } from './workShared';
import { meetingAiApi, type GeneratedMinutes, type MinutesActionDraft } from './workAiApi';
import './work.css';

const NOT_SUPPORTED = '백엔드 미지원 — Jasper PDF 파이프라인 연동 후 활성화';

export function MeetingPage() {
  const qc = useQueryClient();
  const { show, node: toast } = useToast();
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [composing, setComposing] = useState(false);
  const [minutesDraft, setMinutesDraft] = useState('');
  const [transcriptDraft, setTranscriptDraft] = useState('');
  const [actionText, setActionText] = useState('');

  const listQ = useQuery({
    queryKey: ['meetings'],
    queryFn: () => meetingApi.list({ page: 0, size: 50 }),
  });
  const detailQ = useQuery({
    queryKey: ['meeting', selectedId],
    queryFn: () => meetingApi.get(selectedId as string),
    enabled: !!selectedId,
  });

  useEffect(() => {
    if (detailQ.data) {
      setMinutesDraft(detailQ.data.meeting.minutes ?? '');
      setTranscriptDraft('');
    }
  }, [detailQ.data]);

  const createM = useMutation({
    mutationFn: (b: MeetingSaveRequest) => meetingApi.create(b),
    onSuccess: (m) => {
      show('회의가 등록되었습니다.');
      setComposing(false);
      setSelectedId(m.id);
      qc.invalidateQueries({ queryKey: ['meetings'] });
    },
    onError: (e) => show(errMessage(e)),
  });
  const minutesM = useMutation({
    mutationFn: ({ id, minutes, transcript }: { id: string; minutes: string; transcript?: string }) =>
      meetingAiApi.saveMinutes(id, minutes, transcript),
    onSuccess: () => {
      show('회의록이 저장되었습니다.');
      qc.invalidateQueries({ queryKey: ['meeting', selectedId] });
    },
    onError: (e) => show(errMessage(e)),
  });
  const bulkActionsM = useMutation({
    mutationFn: ({ id, items }: { id: string; items: MinutesActionDraft[] }) =>
      meetingAiApi.addActionsBulk(id, items),
    onSuccess: () => {
      show('액션아이템이 등록되었습니다.');
      qc.invalidateQueries({ queryKey: ['meeting', selectedId] });
    },
    onError: (e) => show(errMessage(e)),
  });
  const actionM = useMutation({
    mutationFn: ({ id, item }: { id: string; item: string }) =>
      meetingApi.addAction(id, { actionItem: item }),
    onSuccess: () => {
      setActionText('');
      qc.invalidateQueries({ queryKey: ['meeting', selectedId] });
    },
    onError: (e) => show(errMessage(e)),
  });
  const actionStatusM = useMutation({
    mutationFn: ({ actionId, value }: { actionId: string; value: string }) =>
      meetingApi.actionStatus(actionId, value),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['meeting', selectedId] }),
    onError: (e) => show(errMessage(e)),
  });

  const rows = listQ.data?.items ?? [];

  return (
    <div className="kx-page">
      <header className="kx-work__head">
        <div>
          <h1 className="kx-work__title">회의록</h1>
          <p className="kx-work__subtitle">사전업무협의(D-30) 회의 기록 · 액션아이템 관리</p>
        </div>
        <Button leadingIcon={<IconPlus size={16} />} onClick={() => setComposing(true)}>
          회의 등록
        </Button>
      </header>

      <div className="kx-meet">
        {/* 목록 */}
        <section className="kx-card" aria-label="회의 목록" style={{ padding: 0 }}>
          <div className="kx-scroll-70">
            {listQ.isLoading &&
              Array.from({ length: 5 }).map((_, i) => (
                <div className="kx-meet__list-item" key={i}>
                  <Skeleton height={16} width="70%" />
                  <Skeleton height={13} width="40%" />
                </div>
              ))}
            {listQ.isError && (
              <ErrorState message={errMessage(listQ.error)} onRetry={() => listQ.refetch()} />
            )}
            {!listQ.isLoading && !listQ.isError && rows.length === 0 && (
              <EmptyState title="등록된 회의가 없습니다" />
            )}
            {rows.map((m) => (
              <div
                key={m.id}
                className={`kx-meet__list-item ${selectedId === m.id ? 'is-selected' : ''}`}
                onClick={() => {
                  setComposing(false);
                  setSelectedId(m.id);
                }}
              >
                <span className="kx-list-table__title">{m.title}</span>
                <span className="kx-detail__meta">
                  {fmtDateTime(m.meetingAt)}
                  {m.location && ` · ${m.location}`}
                </span>
              </div>
            ))}
          </div>
        </section>

        {/* 상세 */}
        <section className="kx-detail" aria-label="회의 상세" style={{ position: 'static' }}>
          {composing ? (
            <MeetingCompose
              saving={createM.isPending}
              onCancel={() => setComposing(false)}
              onSave={(b) => createM.mutate(b)}
            />
          ) : !selectedId ? (
            <EmptyState title="회의를 선택하세요" description="목록에서 회의를 선택하면 상세가 표시됩니다." />
          ) : detailQ.isLoading ? (
            <>
              <Skeleton height={24} width="60%" />
              <Skeleton height={120} />
            </>
          ) : detailQ.isError ? (
            <ErrorState message={errMessage(detailQ.error)} onRetry={() => detailQ.refetch()} />
          ) : detailQ.data ? (
            <>
              <div className="kx-detail__head">
                <h2 className="kx-detail__title">{detailQ.data.meeting.title}</h2>
                <span title={NOT_SUPPORTED} style={{ display: 'inline-flex' }}>
                  <Button variant="secondary" disabled leadingIcon={<IconDownload size={16} />}>
                    회의록 PDF
                  </Button>
                </span>
              </div>
              <div className="kx-detail__meta">
                <span>{detailQ.data.meeting.organizerName}</span>
                <span>· {fmtDateTime(detailQ.data.meeting.meetingAt)}</span>
                {detailQ.data.meeting.location && <span>· {detailQ.data.meeting.location}</span>}
              </div>

              {/* 녹음 업로드 → STT 전사 → AI 회의록 자동작성 (G-06) */}
              <MeetingAiPanel
                title={detailQ.data.meeting.title}
                onTranscript={(t) => setTranscriptDraft(t)}
                onMinutes={(g) => {
                  if (g.minutesText) setMinutesDraft(g.minutesText);
                }}
                onAdoptActions={(items) =>
                  bulkActionsM.mutate({ id: detailQ.data!.meeting.id, items })
                }
                adopting={bulkActionsM.isPending}
                show={show}
              />

              {detailQ.data.meeting.content && (
                <div className="kx-field">
                  <span className="kx-label">회의 안건</span>
                  <div className="kx-detail__body">{detailQ.data.meeting.content}</div>
                </div>
              )}

              {/* 회의록 편집 */}
              <div className="kx-field">
                <span className="kx-label">회의록</span>
                <textarea
                  className="kx-textarea"
                  style={{ minHeight: 140 }}
                  value={minutesDraft}
                  onChange={(e) => setMinutesDraft(e.target.value)}
                  placeholder="회의 내용을 기록하세요."
                />
                <div style={{ marginTop: 8 }}>
                  <Button
                    disabled={minutesM.isPending}
                    onClick={() =>
                      minutesM.mutate({
                        id: detailQ.data!.meeting.id,
                        minutes: minutesDraft,
                        transcript: transcriptDraft || undefined,
                      })
                    }
                  >
                    {minutesM.isPending ? '저장 중…' : '회의록 저장'}
                  </Button>
                </div>
              </div>

              {/* 액션아이템 */}
              <div className="kx-field">
                <span className="kx-label">액션아이템</span>
                <table className="kx-list-table">
                  <thead>
                    <tr>
                      <th style={{ width: 40 }}>#</th>
                      <th>내용</th>
                      <th style={{ width: 96 }}>상태</th>
                    </tr>
                  </thead>
                  <tbody>
                    {detailQ.data.actions.length === 0 && (
                      <tr>
                        <td colSpan={3} className="kx-list-table__muted">
                          등록된 액션아이템이 없습니다.
                        </td>
                      </tr>
                    )}
                    {detailQ.data.actions.map((a) => (
                      <tr key={a.id} style={{ cursor: 'default' }}>
                        <td className="kx-num">{a.seq}</td>
                        <td>{a.actionItem}</td>
                        <td>
                          <button
                            className="kx-pill kx-pill--neutral"
                            style={{ cursor: 'pointer', border: 'none' }}
                            onClick={() =>
                              actionStatusM.mutate({
                                actionId: a.id,
                                value: a.status === 'DONE' ? 'OPEN' : 'DONE',
                              })
                            }
                            title="상태 토글"
                          >
                            <StatusPill value={a.status} />
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
                <div className="kx-thread__compose" style={{ marginTop: 8 }}>
                  <input
                    className="kx-input"
                    placeholder="새 액션아이템…"
                    value={actionText}
                    onChange={(e) => setActionText(e.target.value)}
                    onKeyDown={(e) =>
                      e.key === 'Enter' &&
                      actionText.trim() &&
                      actionM.mutate({ id: detailQ.data!.meeting.id, item: actionText })
                    }
                  />
                  <Button
                    disabled={!actionText.trim() || actionM.isPending}
                    onClick={() => actionM.mutate({ id: detailQ.data!.meeting.id, item: actionText })}
                  >
                    추가
                  </Button>
                </div>
              </div>
            </>
          ) : null}
        </section>
      </div>
      {toast}
    </div>
  );
}

/**
 * G-06 회의 녹음 → STT → AI 회의록 패널.
 * 녹음 업로드(≤20MB) → 서버 STT 시도(불가 시 degraded=수동 입력) → 전사 텍스트 → Claude 회의록 자동작성.
 * 결과(요약·결정·액션)는 상위로 전달해 회의록 textarea 프리필 + 액션아이템 일괄 등록.
 */
function MeetingAiPanel({
  title,
  onTranscript,
  onMinutes,
  onAdoptActions,
  adopting,
  show,
}: {
  title: string;
  onTranscript: (t: string) => void;
  onMinutes: (g: GeneratedMinutes) => void;
  onAdoptActions: (items: MinutesActionDraft[]) => void;
  adopting: boolean;
  show: (msg: string) => void;
}) {
  const fileRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);
  const [sttRunning, setSttRunning] = useState(false);
  const [sttDegraded, setSttDegraded] = useState(false);
  const [transcript, setTranscript] = useState('');
  const [fileName, setFileName] = useState<string | null>(null);
  const [generating, setGenerating] = useState(false);
  const [generated, setGenerated] = useState<GeneratedMinutes | null>(null);

  function updateTranscript(v: string) {
    setTranscript(v);
    onTranscript(v);
  }

  async function onPickFile(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    e.target.value = ''; // 같은 파일 재선택 허용
    if (!file) return;
    if (file.size > 20 * 1024 * 1024) {
      show('녹음 파일은 20MB 이하만 업로드할 수 있습니다.');
      return;
    }
    setFileName(file.name);
    setGenerated(null);
    try {
      setUploading(true);
      const up = await meetingAiApi.uploadAudio(file);
      setUploading(false);
      setSttRunning(true);
      const res = await meetingAiApi.stt(up.audioId);
      setSttDegraded(res.degraded);
      if (res.degraded) {
        show('서버 전사를 사용할 수 없습니다. 전사 내용을 직접 입력해 주세요.');
      } else {
        updateTranscript(res.transcript);
        show('전사가 완료되었습니다.');
      }
    } catch (err) {
      show(errMessage(err));
    } finally {
      setUploading(false);
      setSttRunning(false);
    }
  }

  async function onGenerate() {
    if (!transcript.trim()) {
      show('전사 또는 회의 내용을 먼저 입력해 주세요.');
      return;
    }
    try {
      setGenerating(true);
      const g = await meetingAiApi.generateMinutes({ title, transcript });
      setGenerated(g);
      onMinutes(g);
      if (g.degraded) {
        show('AI 회의록 자동작성을 사용할 수 없어 전사 원문을 본문에 반영했습니다.');
      } else {
        show('AI 회의록 초안이 작성되었습니다.');
      }
    } catch (err) {
      show(errMessage(err));
    } finally {
      setGenerating(false);
    }
  }

  const busy = uploading || sttRunning;

  return (
    <div className="kx-meet__ai-card">
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
        <AiLabel>회의록 AI</AiLabel>
        <span className="kx-list-table__muted">녹음 업로드 → 전사 → 회의록 자동작성</span>
      </div>

      <div style={{ display: 'flex', gap: 8, marginTop: 10, flexWrap: 'wrap' }}>
        <input
          ref={fileRef}
          type="file"
          accept="audio/*,.m4a,.mp3,.wav,.webm,.ogg,.aac"
          style={{ display: 'none' }}
          onChange={onPickFile}
        />
        <Button
          variant="secondary"
          leadingIcon={<IconUpload size={16} />}
          disabled={busy}
          onClick={() => fileRef.current?.click()}
        >
          {uploading ? '업로드 중…' : sttRunning ? '전사 중…' : '녹음 파일 업로드'}
        </Button>
        <Button
          leadingIcon={<IconSpark size={16} />}
          disabled={busy || generating || !transcript.trim()}
          onClick={onGenerate}
        >
          {generating ? '작성 중…' : 'AI 회의록 자동작성'}
        </Button>
      </div>

      {fileName && (
        <div className="kx-detail__meta" style={{ marginTop: 6 }}>
          <span>{fileName}</span>
          {sttDegraded && <span className="kx-pill kx-pill--neutral">서버 전사 불가 · 직접 입력</span>}
        </div>
      )}

      {/* 전사 텍스트(편집 가능) — degraded 시 직접 입력 경로 */}
      <div className="kx-field" style={{ marginTop: 8 }}>
        <span className="kx-label">전사 내용</span>
        <textarea
          className="kx-textarea"
          style={{ minHeight: 90 }}
          value={transcript}
          onChange={(e) => updateTranscript(e.target.value)}
          placeholder="녹음을 업로드해 전사하거나, 회의 내용을 직접 입력하세요."
        />
      </div>

      {/* AI 결과 미리보기 */}
      {generated && !generated.degraded && (
        <div style={{ marginTop: 8 }}>
          {generated.summary && (
            <div className="kx-field">
              <span className="kx-label">AI 요약</span>
              <div className="kx-detail__body">{generated.summary}</div>
            </div>
          )}
          {generated.decisions.length > 0 && (
            <div className="kx-field">
              <span className="kx-label">결정사항</span>
              <ul style={{ margin: 0, paddingLeft: 18 }}>
                {generated.decisions.map((d, i) => (
                  <li key={i}>{d}</li>
                ))}
              </ul>
            </div>
          )}
          {generated.actionItems.length > 0 && (
            <div className="kx-field">
              <span className="kx-label">추출 액션아이템 ({generated.actionItems.length})</span>
              <ul style={{ margin: '0 0 8px', paddingLeft: 18 }}>
                {generated.actionItems.map((a, i) => (
                  <li key={i}>
                    {a.content}
                    {a.assignee && <span className="kx-list-table__muted"> · {a.assignee}</span>}
                    {a.dueDate && <span className="kx-list-table__muted"> · {a.dueDate}</span>}
                  </li>
                ))}
              </ul>
              <Button
                variant="secondary"
                disabled={adopting}
                onClick={() => onAdoptActions(generated.actionItems)}
              >
                {adopting ? '등록 중…' : '액션아이템 일괄 등록'}
              </Button>
            </div>
          )}
          <p className="kx-list-table__muted" style={{ marginTop: 4 }}>
            AI 초안입니다. 회의록 본문에 반영되었으니 확인 후 저장하세요.
          </p>
        </div>
      )}
    </div>
  );
}

function MeetingCompose({
  onCancel,
  onSave,
  saving,
}: {
  onCancel: () => void;
  onSave: (b: MeetingSaveRequest) => void;
  saving: boolean;
}) {
  const now = new Date();
  const [form, setForm] = useState<MeetingSaveRequest>({
    title: '',
    location: '',
    meetingAt: `${now.toISOString().slice(0, 16)}`,
    content: '',
  });
  return (
    <>
      <div className="kx-detail__head">
        <h2 className="kx-detail__title">회의 등록</h2>
      </div>
      <label className="kx-field">
        <span className="kx-label">제목 *</span>
        <input className="kx-input" value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })} />
      </label>
      <div className="kx-formgrid">
        <label className="kx-field">
          <span className="kx-label">일시 *</span>
          <input
            type="datetime-local"
            className="kx-input"
            value={form.meetingAt}
            onChange={(e) => setForm({ ...form, meetingAt: e.target.value })}
          />
        </label>
        <label className="kx-field">
          <span className="kx-label">장소</span>
          <input
            className="kx-input"
            value={form.location ?? ''}
            onChange={(e) => setForm({ ...form, location: e.target.value })}
          />
        </label>
      </div>
      <label className="kx-field">
        <span className="kx-label">안건</span>
        <textarea
          className="kx-textarea"
          value={form.content ?? ''}
          onChange={(e) => setForm({ ...form, content: e.target.value })}
        />
      </label>
      <div className="kx-detail__actions">
        <Button disabled={!form.title.trim() || saving} onClick={() => onSave(form)}>
          {saving ? '등록 중…' : '등록'}
        </Button>
        <Button variant="ghost" onClick={onCancel}>
          취소
        </Button>
      </div>
    </>
  );
}
