/**
 * InsuWiki Firestore 타입 정의
 * 
 * 스키마 문서: docs/decisions/260208-20.59-firestore-schema.md
 * 생성일: 2026-02-08 21:10
 */

import { Timestamp } from 'firebase/firestore';
export type { Timestamp };

import type { UserRole } from '@/shared/types/roles';
export type { UserRole };
export { ROLE_HIERARCHY, hasMinRole, ROLE_PERMISSIONS } from '@/shared/types/roles';

// ============================================
// User 관련 타입
// ============================================

export interface User {
    id: string;              // Firebase Auth UID
    email: string;           // Google OAuth 이메일
    name: string;            // 표시 이름
    photoURL?: string;       // 프로필 사진
    role: UserRole;
    aiSettings?: AISettings; // AI 설정 (BYOK)
    createdAt: Timestamp;
    lastLoginAt: Timestamp;
    lastActiveAt?: Timestamp;
}

export interface AISettings {
    geminiApiKey?: string;   // 암호화된 API 키
    preferredModel?: string;
    lastUsedAt?: Timestamp;
}

export type ApiKeyService = 'gemini' | 'whisper';

export interface ApiKey {
    encryptedKey: string;    // AES-256 암호화된 API 키
    service: ApiKeyService;
    updatedAt: Timestamp;
}

// ============================================
// Document 관련 타입
// ============================================

export const VISIBILITY_VALUES = ['public', 'private'] as const;
export type Visibility = typeof VISIBILITY_VALUES[number];
export type DocumentStatus = 'draft' | 'pending' | 'in_review' | 'approved' | 'rejected' | 'revision_requested' | 'needs_re_review' | 'published';
export type Priority = 'low' | 'medium' | 'high';

// Phase 5: 문서 카테고리 (5탭 시스템)
export type DocumentCategory =
    | 'medical'    // 🏥 의료
    | 'casualty'   // 🚗 손해
    | 'wealth'     // 💰 자산
    | 'practice'   // ⚖️ 실무
    | 'general';   // 기본값 (미분류)

// ============================================
// 출처/신뢰도 관련 타입 (Phase 2)
// ============================================

export type SourceType =
  | 'policy_pdf'
  | 'regulation'
  | 'newsletter'
  | 'court_ruling'
  | 'kakao_expert'
  | 'kakao_community'
  | 'youtube'
  | 'wiki_editorial'
  | 'user_submitted'
  | 'dashboard_insight';

export type VerificationStatus =
  | 'unverified'
  | 'auto_passed'
  | 'expert_verified';

export interface SourceMeta {
  channelName?: string;
  expertName?: string;
  collectedAt: Timestamp;
  sourceHash: string;
  verifiedBy?: string;
  verifiedAt?: Timestamp;
  expiresAt?: Timestamp;
  publishedBy?: string;
}

export interface SourceRef {
  channelId: string;
  channelName: string;
  collectedAt: Timestamp;
  messageRef?: string;
}

export interface DocumentProperties {
    status?: DocumentStatus;
    category?: string;
    priority?: Priority;
    assignee?: string;
    dueDate?: Timestamp;
}

export interface Document {
    id: string;
    title: string;
    content: string;         // 마크다운 본문
    visibility: Visibility;  // Default: 'public'
    authorId: string;
    authorName: string;      // 비정규화

    // Obsidian Properties
    properties: DocumentProperties;

    // 문서 타입 (Phase 3 추가)
    docType?: 'wiki' | 'daily';

    // Phase 5: 문서 카테고리 (5탭 시스템)
    category?: DocumentCategory;

    // ── Q&A 형식 콘텐츠 ──
    question?: string;
    answer?: string;
    subcategory?: string;

    // ── 출처/신뢰도 ──
    sourceType?: SourceType;
    verificationStatus?: VerificationStatus;
    authorityTier?: number;
    sourceMeta?: SourceMeta;
    sourceRef?: SourceRef;

    // Phase 5: 백링크 허브용 (인바운드 링크 수)
    incomingLinkCount?: number;

    // 검색용 (Cloud Functions로 자동 생성)
    searchKeywords: string[];

    // 백링크용 (WikiLink 저장 시 자동 생성)
    outgoingLinks?: string[]; // 문서 내에서 링크된 다른 문서들의 제목 목록 (Backlink용)
    outgoingLinkIds?: string[]; // 문서 내에서 링크된 다른 문서들의 ID 목록 (ID 기반 링크용)
    contributorIds?: string[]; // 기여자 ID 목록 (지식 사유화 방지용)
    coverImage?: string | null; // Google Drive File ID for card preview

    // File Attachments
    attachments?: {
        fileId: string;
        name: string;
        url: string;
        type: string; // MIME type or 'image', 'pdf', etc.
        uploadedAt: any;
    }[];

    // 타임스탬프
    createdAt: Timestamp;
    updatedAt: Timestamp;

    // 동시 편집용
    editingBy?: string;
    editingByName?: string; // 표시용 이름
    editingAt?: Timestamp;
    version: number; // For optimistic locking

    // Soft Delete fields
    isDeleted?: boolean;
    deletedAt?: Timestamp;
    deletedBy?: string;

    // 검토 시스템 필드 (Week 2)
    riskLevel?: 'low' | 'high';
    reliabilityScores?: {
        compositeScore?: number;
        verificationScore?: number;
        authorityScore?: number;
        sourceScore?: number;
        reviewScore?: number;
        freshnessScore?: number;
        sourceRefScore?: number;
    };

    // Phase 3 준비: 엔티티 추출
    extractedEntities?: Array<{
        text: string;
        type: 'person' | 'organization' | 'regulation' | 'product' | 'term';
        startOffset?: number;
        endOffset?: number;
    }>;

    // Phase 3 준비: 엔티티 간 교차 연결
    entityLinks?: Array<{
        entityText: string;
        linkedDocId: string;
        linkedDocTitle: string;
        confidence?: number;
    }>;

    insightEntryId?: string;
    originalSourceType?: SourceType;
}

export interface DocumentVersion {
    id: string;
    content: string;
    version: number; // For optimistic locking
    tags: string[]; // 태그 ID 목록 (Tag 테이블 참조)
    editorId: string;
    editorName: string;      // 비정규화
    createdAt: Timestamp;
    summary?: string;        // 변경 요약
}

export interface DocumentTag {
    name: string;
    createdAt: Timestamp;
}

// ============================================
// Link 관련 타입 (백링크)
// ============================================

export type LinkMethod = 'manual' | 'static' | 'embedding' | 'semantic';
export type LinkCreatedBy = 'user' | 'system' | 'ai';
export type LinkStatus = 'active' | 'pending';

export interface Link {
    id: string;
    sourceDocId: string;
    sourceTitle: string;     // 비정규화
    targetDocId: string;
    targetTitle: string;     // 비정규화
    method?: LinkMethod;
    confidence?: number;     // 0-100
    createdBy?: LinkCreatedBy;
    status?: LinkStatus;
    explanation?: string;
    createdAt: Timestamp;
    updatedAt?: Timestamp;
}

export interface AiSuggestion {
    id: string;
    targetDocId: string;
    targetTitle: string;
    method: LinkMethod;
    confidence: number;      // 0-100
    createdBy: LinkCreatedBy;
    explanation?: string;
    dismissed: boolean;
    createdAt: Timestamp;
}

// ============================================
// Daily Notes 타입
// ============================================

export interface DailyNote {
    id: string;
    userId: string;
    date: string;            // "2026-02-08" 형식
    content: string;
    createdAt: Timestamp;
    updatedAt: Timestamp;
}

// ============================================
// Draft 타입 (Quick Capture)
// ============================================

export interface Draft {
    id: string;
    userId: string;
    content: string;
    convertedToDocId?: string;  // 문서로 변환 시 연결
    createdAt: Timestamp;
}

// ============================================
// AutoSave Draft 타입 (편집 중 자동 임시저장)
// ============================================

export interface AutoSaveDraft {
    documentId: string;          // 편집 중인 문서 ID
    userId: string;              // 작성자 UID
    title: string;               // 편집 중인 제목
    content: string;             // 편집 중인 마크다운 내용
    contentHash: string;         // SHA-256 앞 16자 (중복 저장 방지)
    category?: DocumentCategory; // 편집 중인 카테고리
    savedAt: Timestamp;          // 임시저장 시각
    expiresAt: Timestamp;        // 만료 시각 (savedAt + 24시간)
    schemaVersion: number;       // 스키마 버전 (현재 1)
}

// ============================================
// Whitelist 타입
// ============================================

export interface WhitelistEntry {
    email: string;
    addedBy: string;
    addedAt: Timestamp;
    role: UserRole;
}

// ============================================
// RAG & AI Query 관련 타입 (Phase 6 / Option F)
// ============================================

export type JobStatus = 'pending' | 'indexing' | 'complete' | 'failed';
export type QueryType = 'TABLE_QUERY' | 'VECTOR_SEARCH' | 'DEEP_QUERY' | 'COMPLEX' | 'AMBIGUOUS';

export interface Job {
    id: string;
    userId?: string;          // pdf_query에서 필수, index_pdf에서는 시스템 생성이므로 optional
    status: JobStatus;
    type: 'pdf_query' | 'index_pdf';
    queryType?: QueryType;   // v2: 질의 유형 분류 (§5)
    question?: string;
    companyId?: string;      // v2: optional (B형은 회사 없이 가능)
    productId?: string;      // v2: optional
    answer?: string;         // 완료 시
    citations?: string[];    // 완료 시 출처 ("상품명 약관 23p" 형식)
    confidenceScore?: number; // v2: 유사도 점수 (0.0~1.0)
    hasDisclaimerAttached?: boolean; // v2: 면책 문구 포함 여부
    error?: string;          // 실패 시
    // index_pdf job용 필드
    driveFileId?: string;
    companyName?: string;
    productName?: string;
    category?: 'life' | 'non_life' | 'variable';
    effectiveDate?: string;
    chunksCount?: number;    // 완료 시 생성된 청크 수
    createdAt: Timestamp;
    updatedAt: Timestamp;
    expireAt: Timestamp;     // TTL (10분 후 자동 삭제)
}

export interface GeminiFileCache {
    id: string;
    fileKey: string;         // 회사ID_상품ID_해시
    companyId: string;
    productId: string;
    driveFileId: string;
    geminiFileId: string;
    geminiFileUri: string;
    mimeType: string;
    createdAt: Timestamp;
    expireAt: Timestamp;     // TTL (48시간 후 자동 삭제)
}

export type GenerationType = 'gen1' | 'gen2' | 'gen3' | 'gen4';

export interface InsuranceMetadata {
    id: string;              // productId_effectiveDate (버전별 별도 문서)
    companyId: string;
    companyName: string;
    productId: string;
    productName: string;
    category: 'life' | 'non_life' | 'variable';
    driveFolderId?: string;
    driveFileId?: string;
    driveFileName?: string;
    pageCount?: number;
    effectiveDateRange?: { start: string; end?: string }; // v2: "2024-03" 형식, end 없음 = 현행 버전
    generationType?: GenerationType; // 약관 세대 구분
    isSalesStopped: boolean; // v2: 판매 중단 여부 (조회는 계속 허용)
    isActive: boolean;
    createdAt: Timestamp;
    updatedAt: Timestamp;
}

// ── insurance_chunks (B형 Vector RAG용) ──────────────────────────────
export interface InsuranceChunk {
    id: string;
    companyId: string;
    companyName: string;
    productId: string;
    productName: string;
    pageNumber: number;
    chunkText: string;
    embedding: number[];         // Gemini Text Embedding 768차원
    coverageNames: string[];     // v2: 담보명 태깅 (Disambiguation용)
    sourceType: 'policy' | 'newsletter' | 'wiki' | 'youtube' | 'premium_table' | 'appendix'; // v2: 출처 유형 (appendix 추가)
    appendixType?: 'surgery_table' | 'disability_table' | 'disease_code' | 'other'; // Phase 2: 별표 분류
    relatedAppendixIds?: string[]; // Phase 2: 참조하는 별표 청크 ID 목록
    effectiveDate: string;       // "2024-03"
    driveFileId: string;
    sectionId?: string;          // Level 2 요약과 연결용
    createdAt: Timestamp;
    // ⚠️ 보험료/해지환급금 표 내용은 절대 저장 금지 (insurance_tables로 분리)
}

// ── insurance_chunks_archive (과거 버전 영구 보존) ──
export interface InsuranceChunkArchive extends InsuranceChunk {
    archivedAt: Timestamp;
    supersededByDate: string;    // 교체된 버전의 effectiveDate ("YYYY-MM")
    originalDocId: string;       // 원본 insurance_chunks 문서 ID
}

// ── insurance_appendices (별표/부속서류 전용 컬렉션, CL-9) ────────────────
export interface InsuranceAppendix {
    id: string;
    productId: string;
    appendixType: 'surgery_table' | 'disability_table' | 'disease_code' | 'other';
    content: string;                    // 원문 텍스트
    parsedTable: {                      // 마크다운 테이블 파싱 결과 (실패 시 null)
        headers: string[];
        rows: string[][];
    } | null;
    markdownTable: string | null;       // 마크다운 테이블 문자열 (실패 시 null)
    sourceChunkIds: string[];           // 관련 insurance_chunks 문서 ID 목록
    createdAt: Timestamp;
}

// ── index_logs (인덱싱 이력 강화용) ────────────────────────────────
export interface IndexLog {
    id: string;
    productId: string;
    companyId: string;
    jobId: string;
    isReindex: boolean;
    blueGreenMode: boolean;
    previousChunksCount: number;
    newChunksCount: number;
    addedArticles: number;       // 추가된 조항 수
    removedArticles: number;     // 삭제된 조항 수
    avgChunkSize: number;        // 평균 청크 크기
    provisoPreservationRate: number; // 단서조항 보존율 (0~1)
    switchedAt?: Timestamp;      // Blue-Green 스위칭 시각
    createdAt: Timestamp;
}

// ── api_usage_daily (일일 API 사용량, 비용 모니터링) ────────────────
export interface ApiUsageDaily {
    id: string;                  // "YYYY-MM-DD" 형식
    date: string;
    firestoreReads: number;
    firestoreWrites: number;
    geminiEmbeddingCalls: number;
    geminiGenerationCalls: number;
    estimatedCostUsd: number;
    queryCalls: number;
    cacheHits: number;
    cacheMisses: number;
    hourlyQueryCounts: Record<string, number>;  // "HH" → count
    createdAt: Timestamp;
    updatedAt: Timestamp;
}

// ── insurance_terms (용어 사전, v2 §11) ─────────────────────────────
export interface InsuranceTerm {
    id: string;
    term: string;
    definition: string;
    commonAliases: string[];     // 동의어: "뇌졸중" → "뇌혈관질환"
    icdCodes?: string[];         // ICD 질병코드
    companyId: string;
    productId: string;
    pageNumber: number;
    verified: boolean;           // 관리자 검수 완료 여부
    createdAt: Timestamp;
}

// ── insurance_summaries (3단계 요약, Phase 2) ────────────────────────
export type SummaryLevel = 1 | 2 | 3;

export interface InsuranceSummary {
    id: string;
    productId: string;
    companyId: string;
    level: SummaryLevel;          // 1=핵심, 2=섹션, 3=상세(chunks 참조)
    sectionTitle?: string;         // Level 2일 때 장/절 제목
    content: string;               // 요약 본문
    pageRange?: { start: number; end: number }; // 해당 페이지 범위
    createdAt: Timestamp;
    updatedAt: Timestamp;
}

// ── summary_jobs (요약 작업 큐, Phase 2) ─────────────────────────────
export type SummaryJobStatus = 'pending' | 'processing' | 'complete' | 'failed';

export interface SummaryJob {
    id: string;
    productId: string;
    companyId: string;
    companyName: string;
    productName: string;
    driveFileId: string;
    chunksCount: number;           // 생성된 청크 수
    status: SummaryJobStatus;
    error?: string;                // 실패 시 에러 메시지
    createdAt: Timestamp;
    updatedAt: Timestamp;
}

// ── query_cache (쿼리 캐시, Phase 1) ────────────────────────────────
export interface QueryCache {
    id: string;              // 쿼리해시_productId_version
    queryHash: string;       // SHA-256 해시
    productId: string;
    version: string;         // effectiveDate ("2024-03" 형식)
    query: string;           // 원본 쿼리 (디버깅용)
    result: string;          // 캐싱된 응답
    citations?: string[];    // 출처 목록
    confidenceScore?: number;
    createdAt: Timestamp;
    expireAt: Timestamp;     // TTL (24시간 후 자동 삭제)
}

// ── rate_limits (요청 제한, Phase 1) ────────────────────────────────
export type RateLimitWindow = 'minute' | 'hour' | 'day';

export interface RateLimitRecord {
    id: string;              // identifier_window
    identifier: string;      // uid 또는 IP
    window: RateLimitWindow;
    count: number;
    windowStart: Timestamp;
}

// ── ai_feedback (CL-7 피드백 루프) ──────────────────────────────────
export type FeedbackRating = 'positive' | 'negative';
export type FeedbackErrorType = 'exemption_missing' | 'product_confusion' | 'old_version' | 'other';

export interface AiFeedback {
    id: string;
    queryId: string;
    rating: FeedbackRating;
    errorType?: FeedbackErrorType;
    freeText?: string;
    query: string;
    answer: string;
    userId: string;
    createdAt: Timestamp;
}

// ── answer_feedback (피드백 루프, Phase 2) ──────────────────────────
export type FeedbackType = 'correct' | 'incorrect' | 'incomplete';

export interface AnswerFeedback {
    id: string;
    queryId: string;              // query_logs 문서 ID
    feedbackType: FeedbackType;
    comment?: string;             // 사용자 코멘트 (선택)
    userId: string;               // 피드백 제출 사용자
    needsReview: boolean;         // 관리자 리뷰 필요 여부 (incorrect/incomplete → true)
    reviewedAt?: Timestamp;       // 관리자 리뷰 완료 시점
    reviewedBy?: string;          // 리뷰 관리자 ID
    createdAt: Timestamp;
}

// ── query_logs (감사 로그, v2 §13) ──────────────────────────────────
export interface QueryLog {
    id: string;
    agentId: string;
    sessionId: string;
    question: string;
    queryType: QueryType;
    sourceDocs: string[];
    answer: string;
    confidenceScore: number;
    hasDisclaimerAttached: boolean;
    feedbackStatus?: 'correct' | 'incorrect' | 'incomplete';
    timestamp: Timestamp;
}

// ── conversation_sessions (대화 세션, v2 §10) ────────────────────────
export interface ConversationSession {
    id: string;
    agentId: string;
    context: {
        lastCompanyId?: string;
        lastProductId?: string;
        lastCoverageId?: string;
        lastQueryType?: QueryType;
        resolvedParams?: Record<string, string>;
    };
    history: Array<{ role: 'user' | 'assistant'; content: string; timestamp: Timestamp }>;
    createdAt: Timestamp;
    expireAt: Timestamp;         // 30분 비활성 시 종료
}

// ── youtube_channels (v2 §12) ────────────────────────────────────────
export interface YoutubeChannel {
    id: string;
    channelId: string;
    channelName: string;
    isActive: boolean;
    lastCrawledAt: Timestamp;
}

// ── youtube_knowledge (v2 §12) ───────────────────────────────────────
export type SummaryStatus = 'pending' | 'done';

export interface YoutubeKnowledge {
    id: string;
    videoId: string;
    channelId: string;
    channelName: string;
    title: string;
    publishedAt: Timestamp;      // 영상 업로드 시점 (약관 시점 비교용)
    chunkText: string;
    embedding: number[];
    relatedCompanyIds: string[];
    relatedProductIds: string[];
    conflictsWithPolicy: boolean; // 약관과 상충 여부
    conflictDetail?: string;
    sourceType: 'youtube';       // 4순위 권위, 단독 인용 금지
    driveUrl?: string;           // 요약 Drive URL
    hasTranscript?: boolean;     // 자막 여부
    transcriptionSource?: 'youtube_caption' | 'whisper_stt' | 'title_description'; // Phase 1: 전사 출처
    driveTranscriptUrl?: string; // Phase 2: 전문 Drive URL
    summaryStatus?: SummaryStatus; // 요약 상태: 'pending' = 아누 요약 대기, 'done' = 완료
    createdAt: Timestamp;
}

// ============================================
// Firestore 경로 상수
// ============================================

export const COLLECTIONS = {
    USERS: 'users',
    API_KEYS: 'apiKeys',
    DOCUMENTS: 'documents',
    VERSIONS: 'versions',
    TAGS: 'tags',
    LINKS: 'links',
    DAILY_NOTES: 'dailyNotes',
    DRAFTS: 'drafts',
    AUTO_SAVE_DRAFTS: 'autoSaveDrafts',
    WHITELIST: 'whitelist',
    REVISIONS: 'revisions',
    JOBS: 'jobs',
    GEMINI_FILE_CACHE: 'gemini_file_cache',
    INSURANCE_CHUNKS: 'insurance_chunks',
    INSURANCE_TERMS: 'insurance_terms',
    INSURANCE_TABLES: 'insurance_tables',
    INSURANCE_SUMMARIES: 'insurance_summaries',
    SUMMARY_JOBS: 'summary_jobs',
    QUERY_LOGS: 'query_logs',
    CONVERSATION_SESSIONS: 'conversation_sessions',
    YOUTUBE_CHANNELS: 'youtube_channels',
    YOUTUBE_KNOWLEDGE: 'youtube_knowledge',
    YOUTUBE_TRANSCRIPTS: 'youtube_transcripts',
    YOUTUBE_SUMMARIES: 'youtube_summaries',
    YOUTUBE_SUMMARY_QUEUE: 'youtube_summary_queue',
    INSURANCE_METADATA: 'insurance_metadata',
    QUERY_CACHE: 'query_cache',
    RATE_LIMITS: 'rate_limits',
    ANSWER_FEEDBACK: 'answer_feedback',
    AI_FEEDBACK: 'ai_feedback',
    INSURANCE_CHUNKS_STAGING: 'insurance_chunks_staging',
    INSURANCE_CHUNKS_ARCHIVE: 'insurance_chunks_archive',
    INDEX_LOGS: 'index_logs',
    API_USAGE_DAILY: 'api_usage_daily',
    INSURANCE_APPENDICES: 'insurance_appendices',
    AI_SUGGESTIONS: 'ai_suggestions',
    WIKI: 'wiki',
} as const;

// ============================================
// 검토 시스템 타입 (Week 2)
// ============================================

export type ReviewDecision = 'approve' | 'reject' | 'request_revision';
export type RiskLevel = 'low' | 'high';
export type AuditAction = 'status_change' | 'review_submitted' | 'lightweight_edit_exempted' | 'reviewer_assigned' | 'risk_level_assessed';
export type EvidenceType = 'policy_clause' | 'regulation' | 'expert_opinion' | 'court_ruling' | 'other';
export type ErrorReportReason = 'factual_error' | 'outdated_info' | 'missing_source' | 'inappropriate_content';

export interface SourceAttachment {
  url: string;
  label: string;
}

export interface Review {
    id: string;
    docId: string;
    reviewerId: string;
    reviewerName: string;
    decision: ReviewDecision;
    comment: string;
    riskLevel: RiskLevel;
    createdAt: Timestamp;
    evidenceType?: EvidenceType;
    sourceAttachments?: SourceAttachment[];
}

export interface ErrorReport {
  id: string;
  docId: string;
  reporterId: string;
  reporterName: string;
  reason: ErrorReportReason;
  memo: string;
  createdAt: Timestamp;
}

export interface AuditLogEntry {
    id: string;
    docId: string;
    action: AuditAction;
    actorId: string;
    actorName?: string;
    previousStatus?: DocumentStatus;
    newStatus?: DocumentStatus;
    metadata?: Record<string, unknown>;
    createdAt: Timestamp;
}
