import { logger } from "../utils/logger";
import { query } from "../database/db";

// 환경 변수로 데이터 소스 선택
const DATA_SOURCE = process.env.DOCUMENT_DATA_SOURCE || "memory";

export interface Document {
  id: string;
  name: string;
  category: "계약서" | "보험" | "세금계산서" | "기타";
  fileSize: number;
  filePath: string;
  mimeType?: string;
  uploadDate: string;
  description?: string;
  uploadedBy?: string;
  relatedEntityType?: string;
  relatedEntityId?: string;
  tags?: string[];
  isArchived: boolean;
  archivedAt?: string;
}

// 메모리 목 데이터
const mockDocuments: Document[] = [
  {
    id: "doc-1",
    name: "2025년 1월 세금계산서.pdf",
    category: "세금계산서",
    fileSize: 1258291,
    filePath: "/uploads/documents/tax-invoice-202501.pdf",
    uploadDate: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),
    description: "1월 매출 세금계산서",
    uploadedBy: "admin",
    isArchived: false,
  },
  {
    id: "doc-2",
    name: "차량보험증권_서울12가3456.pdf",
    category: "보험",
    fileSize: 876544,
    filePath: "/uploads/documents/insurance-vehicle-1.pdf",
    uploadDate: new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString(),
    description: "1톤 트럭 종합보험",
    uploadedBy: "admin",
    isArchived: false,
  },
  {
    id: "doc-3",
    name: "운송계약서_ABC물류.pdf",
    category: "계약서",
    fileSize: 2457600,
    filePath: "/uploads/documents/contract-abc-logistics.pdf",
    uploadDate: new Date(Date.now() - 15 * 24 * 60 * 60 * 1000).toISOString(),
    description: "ABC물류 연간 운송 계약",
    uploadedBy: "admin",
    isArchived: false,
  },
  {
    id: "doc-4",
    name: "2024년 12월 세금계산서.pdf",
    category: "세금계산서",
    fileSize: 1124353,
    filePath: "/uploads/documents/tax-invoice-202412.pdf",
    uploadDate: new Date(Date.now() - 40 * 24 * 60 * 60 * 1000).toISOString(),
    uploadedBy: "admin",
    isArchived: false,
  },
  {
    id: "doc-5",
    name: "화물배상책임보험증권.pdf",
    category: "보험",
    fileSize: 720384,
    filePath: "/uploads/documents/cargo-insurance.pdf",
    uploadDate: new Date(Date.now() - 50 * 24 * 60 * 60 * 1000).toISOString(),
    description: "화물 배상책임보험",
    uploadedBy: "admin",
    isArchived: false,
  },
  {
    id: "doc-6",
    name: "차고지 임대계약서.pdf",
    category: "계약서",
    fileSize: 1843200,
    filePath: "/uploads/documents/garage-lease-contract.pdf",
    uploadDate: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(),
    uploadedBy: "admin",
    isArchived: false,
  },
];

/**
 * 문서 관리 서비스 (Memory/DB 하이브리드)
 */
export class DocumentService {
  private static instance: DocumentService;

  private constructor() {
    logger.info(`📂 문서 관리 데이터 소스: ${DATA_SOURCE.toUpperCase()}`);
  }

  public static getInstance(): DocumentService {
    if (!DocumentService.instance) {
      DocumentService.instance = new DocumentService();
    }
    return DocumentService.instance;
  }

  public async getAllDocuments(filter?: {
    category?: string;
    searchTerm?: string;
    uploadedBy?: string;
  }): Promise<Document[]> {
    try {
      const documents = DATA_SOURCE === "database"
        ? await this.loadDocumentsFromDB(filter)
        : this.loadDocumentsFromMemory(filter);

      // 최신순 정렬
      documents.sort((a, b) => 
        new Date(b.uploadDate).getTime() - new Date(a.uploadDate).getTime()
      );

      return documents;
    } catch (error) {
      logger.error("❌ 문서 목록 조회 오류:", error);
      throw error;
    }
  }

  public async getDocumentById(id: string): Promise<Document> {
    try {
      if (DATA_SOURCE === "database") {
        return await this.getDocumentByIdDB(id);
      } else {
        return this.getDocumentByIdMemory(id);
      }
    } catch (error) {
      logger.error("❌ 문서 조회 오류:", error);
      throw error;
    }
  }

  public async getStatistics(): Promise<{
    total: number;
    byCategory: Record<string, number>;
    totalSize: number;
  }> {
    try {
      const documents = await this.getAllDocuments();
      
      const byCategory: Record<string, number> = {
        "계약서": 0,
        "보험": 0,
        "세금계산서": 0,
        "기타": 0,
      };

      documents.forEach((doc) => {
        byCategory[doc.category] = (byCategory[doc.category] || 0) + 1;
      });

      const totalSize = documents.reduce((sum, doc) => sum + doc.fileSize, 0);

      return {
        total: documents.length,
        byCategory,
        totalSize,
      };
    } catch (error) {
      logger.error("❌ 문서 통계 조회 오류:", error);
      throw error;
    }
  }

  // ==================== DATABASE 메서드 ====================

  private async loadDocumentsFromDB(filter?: {
    category?: string;
    searchTerm?: string;
    uploadedBy?: string;
  }): Promise<Document[]> {
    let sql = `
      SELECT 
        id, name, category, file_size as "fileSize", file_path as "filePath",
        mime_type as "mimeType", upload_date as "uploadDate",
        description, uploaded_by as "uploadedBy",
        related_entity_type as "relatedEntityType",
        related_entity_id as "relatedEntityId",
        tags, is_archived as "isArchived", archived_at as "archivedAt"
      FROM document_files
      WHERE is_archived = false
    `;
    const params: any[] = [];
    let paramIndex = 1;

    if (filter?.category) {
      sql += ` AND category = $${paramIndex++}`;
      params.push(filter.category);
    }
    if (filter?.searchTerm) {
      sql += ` AND (name ILIKE $${paramIndex} OR description ILIKE $${paramIndex})`;
      params.push(`%${filter.searchTerm}%`);
      paramIndex++;
    }
    if (filter?.uploadedBy) {
      sql += ` AND uploaded_by = $${paramIndex++}`;
      params.push(filter.uploadedBy);
    }

    const rows = await query(sql, params);
    return rows.map((row: any) => ({
      ...row,
      uploadDate: new Date(row.uploadDate).toISOString(),
      archivedAt: row.archivedAt ? new Date(row.archivedAt).toISOString() : undefined,
    }));
  }

  private async getDocumentByIdDB(id: string): Promise<Document> {
    const rows = await query(
      `SELECT 
        id, name, category, file_size as "fileSize", file_path as "filePath",
        mime_type as "mimeType", upload_date as "uploadDate",
        description, uploaded_by as "uploadedBy",
        related_entity_type as "relatedEntityType",
        related_entity_id as "relatedEntityId",
        tags, is_archived as "isArchived", archived_at as "archivedAt"
      FROM document_files
      WHERE id = $1`,
      [id]
    );

    if (rows.length === 0) {
      throw new Error(`문서를 찾을 수 없습니다: ${id}`);
    }

    const row = rows[0];
    return {
      ...row,
      uploadDate: new Date(row.uploadDate).toISOString(),
      archivedAt: row.archivedAt ? new Date(row.archivedAt).toISOString() : undefined,
    };
  }

  // ==================== MEMORY 메서드 ====================

  private loadDocumentsFromMemory(filter?: {
    category?: string;
    searchTerm?: string;
    uploadedBy?: string;
  }): Document[] {
    let documents = mockDocuments.filter((d) => !d.isArchived);

    if (filter?.category) {
      documents = documents.filter((d) => d.category === filter.category);
    }
    if (filter?.searchTerm) {
      const term = filter.searchTerm.toLowerCase();
      documents = documents.filter(
        (d) =>
          d.name.toLowerCase().includes(term) ||
          d.description?.toLowerCase().includes(term)
      );
    }
    if (filter?.uploadedBy) {
      documents = documents.filter((d) => d.uploadedBy === filter.uploadedBy);
    }

    return documents;
  }

  private getDocumentByIdMemory(id: string): Document {
    const document = mockDocuments.find((d) => d.id === id);

    if (!document) {
      throw new Error(`문서를 찾을 수 없습니다: ${id}`);
    }

    return document;
  }
}

