import React, { useState } from 'react';
import type { Note, NoteStatus } from '@shared/types';
import { KST_OFFSET_MS } from '@shared/util/kstDate.js';
import { inboxApi } from '../api.js';
import { useInbox } from '../store.js';
import { EditableField } from './EditableField.js';
import { IntentBanner } from './IntentBanner.js';
import { pushTagUndo } from './TagUndoToast.js';
import { MoveStatusModal, statusLabelWithParticle } from './MoveStatusModal.js';
import { RevisionHistoryModal } from './RevisionHistoryModal.js';

interface Props {
  note: Note;
  onDeleted?: () => void;  // inbox mode 전용 (trash mode 에서 미사용)
  onUpdated: (n: Note) => void;
  mode?: 'inbox' | 'trash';  // default 'inbox'
  onRestore?: () => void;
  onPermanentDelete?: () => void;
}

const aiBadgeStyle: React.CSSProperties = {
  display: 'inline-block', marginLeft: 6, padding: '1px 5px',
  background: '#eee', color: '#666', fontSize: 10, borderRadius: 3, verticalAlign: 'middle'
};

function isPastDue(iso: string, today: string): boolean {
  return iso < today; // string comparison works for ISO YYYY-MM-DD
}

function todayKstIso(): string {
  const k = new Date(Date.now() + KST_OFFSET_MS);
  return k.toISOString().slice(0, 10);
}

function DueDateBadge({
  value,
  isEdited,
  today,
  onSave
}: {
  value: string | null;
  isEdited: boolean;
  today: string;
  onSave: (next: string) => Promise<void>;
}): React.ReactElement {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value ?? '');

  React.useEffect(() => { if (!editing) setDraft(value ?? ''); }, [value, editing]);

  if (!editing) {
    if (value === null) {
      return (
        <span
          onClick={() => setEditing(true)}
          style={{ fontSize: 11, color: '#bbb', cursor: 'pointer' }}
          title="마감일 추가"
        >
          📅 마감일 추가
        </span>
      );
    }
    const past = isPastDue(value, today);
    return (
      <span style={{ fontSize: 11, display: 'inline-flex', alignItems: 'center', gap: 4 }}>
        <span
          onClick={() => setEditing(true)}
          style={{
            color: past ? '#999' : '#666',
            textDecoration: past ? 'line-through' : 'none',
            cursor: 'pointer'
          }}
          title={past ? '지난 마감일 — 클릭으로 편집' : '클릭으로 편집'}
        >
          📅 {value}
        </span>
        {!isEdited && (
          <span
            style={{
              fontSize: 9, padding: '0 4px', background: '#eee',
              color: '#888', borderRadius: 2
            }}
            title="AI 추출"
          >
            AI
          </span>
        )}
      </span>
    );
  }

  return (
    <input
      type="date"
      value={draft}
      onChange={(e) => setDraft(e.target.value)}
      onBlur={async () => {
        try { await onSave(draft); }
        catch { /* keep editing if invalid */ return; }
        setEditing(false);
      }}
      onKeyDown={(e) => {
        if (e.key === 'Enter') (e.target as HTMLInputElement).blur();
        if (e.key === 'Escape') { setDraft(value ?? ''); setEditing(false); }
      }}
      autoFocus
      style={{ fontSize: 11, padding: 1 }}
    />
  );
}

export function NoteCard({ note, onDeleted, onUpdated, mode = 'inbox', onRestore, onPermanentDelete }: Props): React.ReactElement {
  const isTrash = mode === 'trash';
  // v0.2.9 Cut B Task 13 — ai_status='disabled' 노트는 raw_text 가 1차 정보. 원문 펼침 default 켬.
  const [rawOpen, setRawOpen] = useState(note.aiStatus !== 'done');
  const [local, setLocal] = useState(note);
  const isAiDisabled = local.aiStatus === 'disabled';
  const fallbackTitle = local.rawText.split('\n')[0]?.slice(0, 60) || '(빈 메모)';
  // v0.2.9 Cut B Task 6 — 이동 메뉴 dropdown + MoveStatusModal target.
  const [moveTarget, setMoveTarget] = useState<NoteStatus | null>(null);
  const [menuOpen, setMenuOpen] = useState(false);
  const [editingRaw, setEditingRaw] = useState(false);
  const [draftRaw, setDraftRaw] = useState('');
  const [showRevisions, setShowRevisions] = useState(false);

  const possibleTargets: NoteStatus[] = (
    ['active', 'completed', 'archived', 'trashed'] as NoteStatus[]
  ).filter((s) => s !== local.status);

  React.useEffect(() => { setLocal(note); }, [note]);

  const formatted = new Date(note.createdAt).toLocaleString('ko-KR');

  async function saveTitle(next: string) {
    await inboxApi.updateAiFields(note.id, { title: next });
    const updated = { ...local, aiTitle: next, titleEditedByUser: true };
    setLocal(updated); onUpdated(updated);
  }

  async function saveSummary(next: string) {
    await inboxApi.updateAiFields(note.id, { summary: next });
    const updated = { ...local, aiSummary: next, summaryEditedByUser: true };
    setLocal(updated); onUpdated(updated);
  }

  async function saveDueDate(next: string) {
    const value = next.trim() === '' ? null : next.trim();
    // Light validation: empty or YYYY-MM-DD
    if (value !== null && !/^\d{4}-\d{2}-\d{2}$/.test(value)) {
      throw new Error('Invalid date');
    }
    await inboxApi.setDueDate(note.id, value);
    const updated = { ...local, dueDate: value, dueDateEditedByUser: true };
    setLocal(updated); onUpdated(updated);
  }

  async function saveRaw() {
    const next = draftRaw;
    if (next.trim().length === 0) return;
    const r = await inboxApi.updateRawText(note.id, next);
    if (!r.ok) return;
    const updated = { ...local, rawText: next, updatedAt: new Date().toISOString() };
    setLocal(updated);
    onUpdated(updated);
    setEditingRaw(false);
  }

  async function removeTag(tagName: string) {
    const removed = local.tags.find((t) => t.name === tagName);
    const nextTagNames = local.tags.filter((t) => t.name !== tagName).map((t) => t.name);
    await inboxApi.updateAiFields(note.id, { tags: nextTagNames });
    const updated = { ...local, tags: local.tags.filter((t) => t.name !== tagName) };
    setLocal(updated); onUpdated(updated);

    if (removed !== undefined) {
      pushTagUndo({
        noteId: note.id,
        tag: removed,
        onUndo: async () => {
          // Restore by re-adding the removed tag.
          // Note: source flag is reset to 'user' on the backend by `updateAiFields` (it
          // only takes names), which mirrors current behaviour for any user-driven
          // tag mutation. Visual restoration matches latest local state.
          const restoredNames = [...updated.tags.map((t) => t.name), removed.name];
          await inboxApi.updateAiFields(note.id, { tags: restoredNames });
          const u2 = { ...updated, tags: [...updated.tags, removed] };
          setLocal(u2); onUpdated(u2);
        }
      });
    }
  }

  function filterByTag(tagName: string): void {
    useInbox.getState().setTagFilter(tagName);
  }

  async function saveIntent(next: string) {
    await inboxApi.setIntent(note.id, next);
    const now = new Date().toISOString();
    const updated = { ...local, userIntent: next, intentPromptedAt: local.intentPromptedAt ?? now };
    setLocal(updated); onUpdated(updated);
  }

  const showIntentBanner = local.aiStatus === 'done' && local.intentPromptedAt === null;

  return (
    // id load-bearing — RecallBanner 의 scrollIntoView target (#6 v0.2.3)
    <div id={`note-${note.id}`} style={{ background: 'white', padding: 16, marginBottom: 12, borderRadius: 10, boxShadow: '0 1px 2px rgba(0,0,0,0.04)' }}>
      <div style={{ fontSize: 11, color: '#888' }}>{formatted}</div>

      {!isTrash && showIntentBanner && (
        <IntentBanner
          noteId={note.id}
          onResolved={(intentText) => {
            const now = new Date().toISOString();
            const updated = { ...local, userIntent: intentText ?? null, intentPromptedAt: now };
            setLocal(updated); onUpdated(updated);
          }}
        />
      )}

      {local.aiStatus === 'pending' && (
        <div style={{ fontSize: 16, fontWeight: 600, color: '#666', marginTop: 4 }}>
          Inkling이 정리하는 중…
        </div>
      )}
      {local.aiStatus === 'failed' && (
        <div title={local.aiError ?? ''} style={{ fontSize: 16, fontWeight: 600, color: '#a55', marginTop: 4 }}>
          정리 보류 — 원문은 안전합니다
        </div>
      )}
      {/* v0.2.9 Cut B Task 13 — ai_status='disabled': raw_text 첫 줄 fallback title.
          summary/tags 는 hide. 원문은 아래 "원문 보기" 영역에서 항상 표시. */}
      {isAiDisabled && (
        <div style={{ marginTop: 4 }}>
          <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>{fallbackTitle}</h3>
        </div>
      )}
      {local.aiStatus === 'done' && (
        <>
          {isTrash ? (
            <>
              <div style={{ marginTop: 4 }}>
                <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>{local.aiTitle ?? '(제목 없음)'}</h3>
              </div>
              <div style={{ marginTop: 6, fontSize: 13, color: '#333', whiteSpace: 'pre-wrap' }}>
                {local.aiSummary ?? '(요약 없음)'}
              </div>
              {local.dueDate !== null && (
                <div style={{ marginTop: 6 }}>
                  <span style={{ fontSize: 11, color: '#666' }}>📅 {local.dueDate}</span>
                </div>
              )}
              {local.tags.length > 0 && (
                <div style={{ marginTop: 8, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                  {local.tags.map((t) => (
                    <span
                      key={t.name}
                      style={{
                        background: t.source === 'ai' ? '#eaf3ff' : '#e9f9e4',
                        color: t.source === 'ai' ? '#0a4b80' : '#236b1a',
                        padding: '2px 8px',
                        borderRadius: 12,
                        fontSize: 12
                      }}
                    >
                      {t.name}{t.source === 'ai' && <sub style={{ marginLeft: 3, fontSize: 9 }}>AI</sub>}
                    </span>
                  ))}
                </div>
              )}
            </>
          ) : (
            <>
              <div style={{ marginTop: 4 }}>
                <EditableField
                  value={local.aiTitle ?? ''}
                  onSave={saveTitle}
                  style={{ display: 'inline-block', fontSize: 16, fontWeight: 600 }}
                  singleLine
                />
                {!local.titleEditedByUser && <span style={aiBadgeStyle} title="AI 제안">AI</span>}
              </div>
              <div style={{ marginTop: 6 }}>
                <EditableField
                  value={local.aiSummary ?? ''}
                  onSave={saveSummary}
                  style={{ fontSize: 13, color: '#333', whiteSpace: 'pre-wrap' }}
                  singleLine={false}
                />
                {!local.summaryEditedByUser && <span style={aiBadgeStyle} title="AI 제안">AI</span>}
              </div>
              <div style={{ marginTop: 6 }}>
                <DueDateBadge
                  value={local.dueDate}
                  isEdited={local.dueDateEditedByUser}
                  today={todayKstIso()}
                  onSave={saveDueDate}
                />
              </div>
              {local.tags.length > 0 && (
                <div style={{ marginTop: 8, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                  {local.tags.map((t) => (
                    <span
                      key={t.name}
                      style={{
                        background: t.source === 'ai' ? '#eaf3ff' : '#e9f9e4',
                        color: t.source === 'ai' ? '#0a4b80' : '#236b1a',
                        padding: '2px 4px 2px 8px',
                        borderRadius: 12,
                        fontSize: 12,
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: 4
                      }}
                    >
                      <span
                        onClick={() => filterByTag(t.name)}
                        style={{ cursor: 'pointer' }}
                        title={`#${t.name} 노트만 보기`}
                      >
                        {t.name}{t.source === 'ai' && <sub style={{ marginLeft: 3, fontSize: 9 }}>AI</sub>}
                      </span>
                      <button
                        onClick={(e) => { e.stopPropagation(); void removeTag(t.name); }}
                        style={{
                          background: 'none',
                          border: 'none',
                          cursor: 'pointer',
                          color: 'inherit',
                          fontSize: 14,
                          padding: '0 2px',
                          lineHeight: 1,
                          opacity: 0.6
                        }}
                        title="태그 제거"
                        aria-label={`${t.name} 태그 제거`}
                      >
                        ×
                      </button>
                    </span>
                  ))}
                </div>
              )}
              {local.userIntent !== null && (
                <div style={{ marginTop: 10, padding: 8, background: '#fffbe9', borderRadius: 6 }}>
                  <span style={{ fontSize: 12, color: '#7a5a00', marginRight: 6 }}>💡</span>
                  <EditableField
                    value={local.userIntent}
                    onSave={saveIntent}
                    style={{ display: 'inline-block', fontSize: 13, color: '#444' }}
                    singleLine
                  />
                </div>
              )}
            </>
          )}
        </>
      )}

      {local.media.length > 0 && (
        <div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {local.media.map((m) => (
            // alt="" — decorative (relPath 는 사용자 의미 X). title 이 hover tooltip.
            <img
              key={m.id}
              src={`inkling-media://${m.relPath}`}
              alt=""
              title={m.relPath}
              onClick={() => { void inboxApi.openMedia(m.relPath); }}
              style={{
                width: 48,
                height: 48,
                objectFit: 'cover',
                borderRadius: 4,
                cursor: 'pointer',
                border: '1px solid #e0e0e0'
              }}
            />
          ))}
        </div>
      )}

      <div style={{ marginTop: 10 }}>
        <button onClick={() => setRawOpen((o) => !o)} style={{ background: 'none', border: 'none', color: '#555', fontSize: 12, cursor: 'pointer', padding: 0 }}>
          {rawOpen ? '▾ 원문 접기' : '▸ 원문 보기'}
        </button>
        {rawOpen && (
          <div style={{ marginTop: 6 }}>
            {editingRaw ? (
              <div>
                <textarea
                  aria-label="원문 편집"
                  value={draftRaw}
                  onChange={(e) => setDraftRaw(e.target.value)}
                  style={{ width: '100%', minHeight: 80, fontSize: 12, fontFamily: 'inherit', padding: 8, border: '1px solid #ddd', borderRadius: 4, boxSizing: 'border-box' }}
                />
                <div style={{ marginTop: 4, display: 'flex', gap: 6, justifyContent: 'flex-end' }}>
                  <button onClick={() => setEditingRaw(false)} style={{ background: 'none', border: '1px solid #ccc', color: '#444', cursor: 'pointer', fontSize: 12, padding: '3px 10px', borderRadius: 4 }}>취소</button>
                  <button onClick={() => { void saveRaw(); }} style={{ background: '#0a4b80', border: 'none', color: '#fff', cursor: 'pointer', fontSize: 12, padding: '3px 10px', borderRadius: 4 }}>저장</button>
                </div>
              </div>
            ) : (
              <>
                <pre style={{ margin: 0, whiteSpace: 'pre-wrap', fontSize: 12, color: '#555', background: '#fafafa', padding: 8, borderRadius: 4 }}>
                  {local.rawText}
                </pre>
                <div style={{ marginTop: 4, display: 'flex', gap: 6, justifyContent: 'flex-end' }}>
                  <button onClick={() => setShowRevisions(true)} style={{ background: 'none', border: 'none', color: '#0a4b80', cursor: 'pointer', fontSize: 12, padding: 0 }}>이력</button>
                  <button onClick={() => { setDraftRaw(local.rawText); setEditingRaw(true); }} style={{ background: 'none', border: '1px solid #ccc', color: '#444', cursor: 'pointer', fontSize: 12, padding: '3px 10px', borderRadius: 4 }}>편집</button>
                </div>
              </>
            )}
          </div>
        )}
      </div>

      <div style={{ marginTop: 10, textAlign: 'right' }}>
        <div
          style={{
            display: 'flex',
            gap: 8,
            justifyContent: 'flex-end',
            alignItems: 'center'
          }}
        >
          {/* v0.2.9 Cut B Task 6 — 모든 view 공통 "이동 ▾" dropdown.
              현재 status 와 다른 3개 목적지만 표시. */}
          <div style={{ position: 'relative' }}>
            <button
              onClick={() => setMenuOpen((o) => !o)}
              aria-label="이동"
              style={{
                background: 'none',
                border: '1px solid #ccc',
                color: '#444',
                cursor: 'pointer',
                fontSize: 12,
                padding: '4px 10px',
                borderRadius: 4
              }}
            >
              이동 ▾
            </button>
            {menuOpen && (
              <div
                style={{
                  position: 'absolute',
                  right: 0,
                  top: '100%',
                  marginTop: 2,
                  background: '#fff',
                  border: '1px solid #ccc',
                  borderRadius: 4,
                  padding: 4,
                  zIndex: 10,
                  minWidth: 140,
                  boxShadow: '0 2px 6px rgba(0,0,0,0.08)'
                }}
              >
                {possibleTargets.map((t) => (
                  <button
                    key={t}
                    onClick={() => {
                      setMoveTarget(t);
                      setMenuOpen(false);
                    }}
                    style={{
                      display: 'block',
                      width: '100%',
                      textAlign: 'left',
                      background: 'none',
                      border: 'none',
                      padding: '6px 8px',
                      fontSize: 12,
                      cursor: 'pointer'
                    }}
                  >
                    {statusLabelWithParticle(t)} 이동
                  </button>
                ))}
              </div>
            )}
          </div>

          {/* trash mode 만 영구 삭제 + 복구 보존 (휴지통 단독 액션). */}
          {isTrash && (
            <>
              <button
                onClick={onRestore}
                style={{
                  background: 'none', border: '1px solid #0a4b80', color: '#0a4b80',
                  cursor: 'pointer', fontSize: 12, padding: '4px 10px', borderRadius: 4
                }}
              >
                🔄 복구
              </button>
              <button
                onClick={onPermanentDelete}
                style={{
                  background: 'none', border: '1px solid #c93030', color: '#c93030',
                  cursor: 'pointer', fontSize: 12, padding: '4px 10px', borderRadius: 4
                }}
              >
                🗑 영구 삭제
              </button>
            </>
          )}
        </div>
      </div>

      {moveTarget !== null && (
        <MoveStatusModal
          noteId={local.id}
          rawText={local.rawText}
          summary={local.aiSummary ?? ''}
          onClose={() => setMoveTarget(null)}
          onMoved={(newStatus, reason) => {
            const updated = { ...local, status: newStatus, moveReason: reason };
            setLocal(updated);
            onUpdated(updated);
            // inbox/trash mode 의 list 가 status 별로 필터되므로 onDeleted (제거) 도 호출.
            if (newStatus !== local.status) onDeleted?.();
            setMoveTarget(null);
          }}
        />
      )}
      {showRevisions && (
        <RevisionHistoryModal
          noteId={local.id}
          onClose={() => setShowRevisions(false)}
          onRestored={(newRawText) => {
            const updated = { ...local, rawText: newRawText, updatedAt: new Date().toISOString() };
            setLocal(updated);
            onUpdated(updated);
          }}
        />
      )}
    </div>
  );
}
