declare global {
  namespace Electron { interface App { isQuitting?: boolean; } }
  interface Window { inkling: InklingApi; }
}

export interface NoteMedia {
  id: string;
  kind: 'image';
  relPath: string;
  mime: string;
  bytes: number;
}

export type AiStatus = 'pending' | 'done' | 'failed' | 'disabled';

// v0.2.9 Cut B — 노트 status 4분기 (사용자 액션). m004 마이그레이션 + setStatus.
export type NoteStatus = 'active' | 'completed' | 'archived' | 'trashed';

export interface NoteTag {
  name: string;
  source: 'ai' | 'user';
}

// v0.2.10 Cut C — note_revisions 테이블 row.
// 'capture' = 최초 캡처 시점, 'user' = 사용자가 raw_text 정정한 시점.
export interface NoteRevision {
  revId: number;
  noteId: string;
  rawText: string;
  editedAt: string;
  editedBy: 'user' | 'capture';
}

// v0.2.11 Cut D — 회고 view aggregate.
export type ReviewPeriod = 'daily' | 'weekly' | 'monthly';
export interface ReviewAggregate {
  totalCount: number;
  recentNotes: Note[];
  tagCounts: Array<{ tag: string; count: number }>;
  dueProgress: { total: number; passed: number; pending: number };
}

// v0.3.0 Cut E — 양방향 sync 결과 + conflict.
// `path` = git index 의 conflict 파일 상대경로 (예: 'notes/2026-05-09-abc12345-회의.md').
// F5 export 의 filename 은 date-id8-slug 패턴 — UUID 가 아니라 path 가 맞는 식별자.
export interface SyncConflict {
  path: string;
  localText: string;
  remoteText: string;
}

export interface SyncStatus {
  ok: boolean;
  reason?: string;
  changed?: boolean;
  localSha?: string | null;
  pushed?: boolean;
  importedCount?: number;
  conflicts?: SyncConflict[];
}

export interface SyncStatusSnapshot {
  lastAt: string | null;
  lastResult: SyncStatus | null;
  nextAt: string | null;
}

export interface Note {
  id: string;
  rawText: string;
  aiTitle: string | null;
  aiSummary: string | null;
  aiStatus: AiStatus;
  aiError: string | null;
  aiProvider: string | null;
  aiGeneratedAt: string | null;
  titleEditedByUser: boolean;
  summaryEditedByUser: boolean;
  userIntent: string | null;
  intentPromptedAt: string | null;
  dueDate: string | null;
  dueDateEditedByUser: boolean;
  // 신규 v3:
  deletedAt: string | null;
  lastRecalledAt: string | null;
  recallDismissedAt: string | null;
  // 신규 v4 (v0.2.9 Cut B):
  status: NoteStatus;
  statusChangedAt: string | null;
  moveReason: string | null;
  createdAt: string;
  updatedAt: string;
  tags: NoteTag[];
  media: NoteMedia[];
}

export interface WeeklyContinuity {
  weekStart: string;                 // ISO date (KST 월요일)
  weekCount: number;
  weekTarget: number;                // 7
  consecutiveCompleteWeeks: number;
  showRecoveryToast: boolean;
  lastNoteAt: string | null;
}

export interface CaptureApi {
  submit(payload: { text: string; images: ArrayBuffer[] }): Promise<{ noteId: string }>;
  hide(): void;
}

// v0.2.7 F12 deeper fix — 자동 실행 진단 정보 (AutostartDiagnostic.collectAutostartState 결과).
export interface AutostartDiagnostic {
  withArgs: { openAtLogin: boolean; executableWillLaunchAtLogin: boolean };
  noArgs: { openAtLogin: boolean; executableWillLaunchAtLogin: boolean };
  execPath: string;
  registryPath?: string;
  registryValue?: string | null;
}

export interface AutostartResponse {
  openAtLogin: boolean;
  diagnostic: AutostartDiagnostic;
}

export interface InboxApi {
  listNotes(opts: { limit: number; cursor?: string }): Promise<Note[]>;
  updateAiFields(
    noteId: string,
    fields: { title?: string; summary?: string; tags?: string[] }
  ): Promise<void>;
  setDueDate(noteId: string, date: string | null): Promise<void>;
  deleteNote(noteId: string): Promise<void>;
  setIntent(noteId: string, text: string): Promise<void>;
  dismissIntent(noteId: string): Promise<void>;
  getContinuity(): Promise<WeeklyContinuity>;
  getPendingCount(): Promise<number>;
  getOllamaStatus(): Promise<{ ok: boolean; reason?: string }>;
  getTodayCount(): Promise<number>;
  // 신규 v0.2.3 #4:
  restoreNote(noteId: string): Promise<void>;
  permanentDeleteNote(noteId: string): Promise<{ confirmed: boolean }>;
  emptyTrash(): Promise<{ confirmed: boolean; count: number }>;
  listTrash(opts: { limit: number }): Promise<Note[]>;
  getTrashCount(): Promise<number>;
  listExpired(): Promise<Note[]>;
  trashExpiredBatch(ids: string[]): Promise<{ trashedCount: number; confirmed: boolean }>;
  ollamaRecheck(): Promise<{ ok: boolean; reason?: string }>;
  onNoteUpdated(cb: (note: Note) => void): () => void;
  onOllamaStatus(cb: (status: { ok: boolean; reason?: string }) => void): () => void;
  retryAllFailed(): Promise<{ count: number }>;
  getFailedCount(): Promise<number>;
  listRecallCandidate(): Promise<Note | null>;
  markRecallOpened(id: string): Promise<{ note: Note }>;
  dismissRecall(id: string): Promise<{ note: Note }>;
  emitRecallShown(id: string): void;
  emitRecallSnoozed(id: string): void;
  loadOllamaSettings(): Promise<{ endpoint: string; model: string } | null>;
  saveOllamaSettings(v: { endpoint: string; model: string }): Promise<{ ok: true } | { ok: false; reason: string }>;
  // v0.2.7 Task 13 — 외부 (트레이 등) 에서 view 전환 요청 구독.
  onNavigate(cb: (view: 'inbox' | 'trash' | 'settings') => void): () => void;
  // v0.2.7 자동 실행 (Task 22 통일) — 진단 정보 포함 응답
  getAutostart(): Promise<AutostartResponse>;
  setAutostart(open: boolean): Promise<AutostartResponse>;
  // v0.2.7 백업 / 복원 / 동기화 / 텔레메트리 — 트레이 callback 의 IPC 대응 (Task 10)
  runBackup(): Promise<{ ok: true }>;
  runExport(): Promise<{ ok: true }>;
  runImport(): Promise<{ ok: true }>;
  runSync(): Promise<{ ok: true }>;
  runExportTelemetry(): Promise<{ ok: true }>;
  // 정보 섹션 — 트레이 showAboutDialog 의 IPC 대응.
  getAppInfo(): Promise<{
    version: string;
    electron: string;
    node: string;
    os: string;
    profileDir: string;
  }>;
  openProfileDir(): Promise<void>;
  copyAppInfo(): Promise<void>;
  // v0.2.8 Cut A — 첨부 이미지를 OS 기본 뷰어로 열기 (Task 3).
  openMedia(relPath: string): Promise<{ ok: true } | { ok: false; reason: string }>;
  // v0.2.9 Cut B Task 4 — status 별 노트 목록 + status 별 count.
  listByStatus(status: NoteStatus, opts?: { limit?: number }): Promise<Note[]>;
  countsByStatus(): Promise<{ active: number; completed: number; archived: number; trashed: number }>;
  // v0.2.9 Cut B Task 8 — 4분기 status 전이 + AI 자동 분류 추천.
  setStatus(
    id: string,
    status: NoteStatus,
    reason: string | null
  ): Promise<{ ok: true } | { ok: false; reason: string }>;
  classifyStatus(id: string, reason: string): Promise<{ recommended: NoteStatus; rationale: string }>;
  // v0.2.9 Cut B Task 12 — settings read + AI/onboarding 토글.
  getSettings(): Promise<{
    ollama?: { endpoint: string; model: string };
    ai_enabled?: boolean;
    onboarding_completed?: boolean;
    sync_repo_url?: string | null;
    sync_auto_enabled?: boolean;
    sync_interval_min?: number;
    // v0.3.1 Cut F
    vision_model?: string | null;
    vision_capable_cache?: string[];
    vision_cache_at?: string;
  }>;
  setAiEnabled(enabled: boolean): Promise<{ ok: true }>;
  setOnboardingCompleted(completed: boolean): Promise<{ ok: true }>;
  // v0.2.9 Cut B Task 16 — ai_status='disabled' 메모 재투입 (사용자가 ai_enabled OFF→ON 전환 시).
  enqueueDisabled(): Promise<{ count: number }>;
  getDisabledCount(): Promise<number>;
  // v0.2.10 Cut C — raw_text 가변 + revision 보존.
  updateRawText(noteId: string, newText: string): Promise<{ ok: true } | { ok: false; reason: string }>;
  listRevisions(noteId: string): Promise<NoteRevision[]>;
  restoreRevision(noteId: string, revId: number): Promise<{ ok: true } | { ok: false; reason: string }>;
  // v0.2.11 Cut D — FTS5 search + 회고 aggregate.
  search(query: string, opts?: { limit?: number; status?: NoteStatus }): Promise<Note[]>;
  reviewAggregate(period: ReviewPeriod): Promise<ReviewAggregate>;
  // v0.3.0 Cut E — 양방향 sync.
  configureSync(url: string | null): Promise<{ ok: true } | { ok: false; reason: string }>;
  testSyncConnection(): Promise<{ ok: true } | { ok: false; reason: string }>;
  listConflicts(): Promise<SyncConflict[]>;
  resolveConflict(path: string, choice: 'local' | 'remote'): Promise<{ ok: true } | { ok: false; reason: string }>;
  getSyncStatus(): Promise<SyncStatusSnapshot>;
  setSyncAutoEnabled(enabled: boolean): Promise<{ ok: true }>;
  setSyncIntervalMin(value: number): Promise<{ ok: true } | { ok: false; reason: string }>;
  // v0.3.1 Cut F — vision capability detection + 모델 선택.
  getVisionModels(): Promise<{ models: string[]; at: string | null; selected: string | null }>;
  setVisionModel(value: string | null): Promise<{ ok: true }>;
  refreshVisionCache(): Promise<{ ok: true; models: string[] } | { ok: false; reason: string }>;
}

export interface InklingApi {
  capture: CaptureApi;
  inbox: InboxApi;
}

export {};
