// 수집 관리 서비스
// 작성일: 2024-12-23

import { query, queryOne, transaction } from "../database/db";
import {
  DataCollectionConfig,
  CollectionFilter,
  CollectionJob,
  CollectionHistory,
} from "../types/collectionManagement";

export class CollectionService {
  /**
   * 수집 설정 목록 조회
   */
  static async getCollectionConfigs(
    filter: CollectionFilter
  ): Promise<DataCollectionConfig[]> {
    const whereConditions: string[] = ["company_code = $1"];
    const values: any[] = [filter.company_code || "*"];
    let paramIndex = 2;

    if (filter.config_name) {
      whereConditions.push(`config_name ILIKE $${paramIndex++}`);
      values.push(`%${filter.config_name}%`);
    }

    if (filter.source_connection_id) {
      whereConditions.push(`source_connection_id = $${paramIndex++}`);
      values.push(filter.source_connection_id);
    }

    if (filter.collection_type) {
      whereConditions.push(`collection_type = $${paramIndex++}`);
      values.push(filter.collection_type);
    }

    if (filter.is_active) {
      whereConditions.push(`is_active = $${paramIndex++}`);
      values.push(filter.is_active === "Y");
    }

    if (filter.search) {
      whereConditions.push(
        `(config_name ILIKE $${paramIndex} OR description ILIKE $${paramIndex})`
      );
      values.push(`%${filter.search}%`);
      paramIndex++;
    }

    const configs = await query<any>(
      `SELECT * FROM data_collection_configs 
       WHERE ${whereConditions.join(" AND ")}
       ORDER BY created_date DESC`,
      values
    );

    return configs.map((config: any) => ({
      ...config,
      is_active: config.is_active ? "Y" : "N",
    })) as DataCollectionConfig[];
  }

  /**
   * 수집 설정 상세 조회
   */
  static async getCollectionConfigById(
    id: number
  ): Promise<DataCollectionConfig | null> {
    const config = await queryOne<any>(
      `SELECT * FROM data_collection_configs WHERE id = $1`,
      [id]
    );

    if (!config) return null;

    return {
      ...config,
      is_active: config.is_active ? "Y" : "N",
    } as DataCollectionConfig;
  }

  /**
   * 수집 설정 생성
   */
  static async createCollectionConfig(
    data: DataCollectionConfig
  ): Promise<DataCollectionConfig> {
    const { id, collection_options, ...createData } = data;
    const config = await queryOne<any>(
      `INSERT INTO data_collection_configs 
       (config_name, company_code, source_connection_id, collection_type, 
        collection_options, schedule_cron, is_active, description, 
        created_by, updated_by, created_date, updated_date)
       VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, NOW(), NOW())
       RETURNING *`,
      [
        createData.config_name,
        createData.company_code,
        createData.source_connection_id,
        createData.collection_type,
        collection_options ? JSON.stringify(collection_options) : null,
        createData.schedule_cron,
        data.is_active,
        createData.description,
        createData.created_by,
        createData.updated_by,
      ]
    );

    return {
      ...config,
      is_active: config.is_active ? "Y" : "N",
    } as DataCollectionConfig;
  }

  /**
   * 수집 설정 수정
   */
  static async updateCollectionConfig(
    id: number,
    data: Partial<DataCollectionConfig>
  ): Promise<DataCollectionConfig> {
    const updateFields: string[] = ["updated_date = NOW()"];
    const values: any[] = [];
    let paramIndex = 1;

    if (data.config_name !== undefined) {
      updateFields.push(`config_name = $${paramIndex++}`);
      values.push(data.config_name);
    }
    if (data.source_connection_id !== undefined) {
      updateFields.push(`source_connection_id = $${paramIndex++}`);
      values.push(data.source_connection_id);
    }
    if (data.collection_type !== undefined) {
      updateFields.push(`collection_type = $${paramIndex++}`);
      values.push(data.collection_type);
    }
    if (data.collection_options !== undefined) {
      updateFields.push(`collection_options = $${paramIndex++}`);
      values.push(
        data.collection_options ? JSON.stringify(data.collection_options) : null
      );
    }
    if (data.schedule_cron !== undefined) {
      updateFields.push(`schedule_cron = $${paramIndex++}`);
      values.push(data.schedule_cron);
    }
    if (data.is_active !== undefined) {
      updateFields.push(`is_active = $${paramIndex++}`);
      values.push(data.is_active);
    }
    if (data.description !== undefined) {
      updateFields.push(`description = $${paramIndex++}`);
      values.push(data.description);
    }
    if (data.updated_by !== undefined) {
      updateFields.push(`updated_by = $${paramIndex++}`);
      values.push(data.updated_by);
    }

    const config = await queryOne<any>(
      `UPDATE data_collection_configs 
       SET ${updateFields.join(", ")}
       WHERE id = $${paramIndex}
       RETURNING *`,
      [...values, id]
    );

    return {
      ...config,
      is_active: config.is_active ? "Y" : "N",
    } as DataCollectionConfig;
  }

  /**
   * 수집 설정 삭제
   */
  static async deleteCollectionConfig(id: number): Promise<void> {
    await query(`DELETE FROM data_collection_configs WHERE id = $1`, [id]);
  }

  /**
   * 수집 작업 실행
   */
  static async executeCollection(configId: number): Promise<CollectionJob> {
    const config = await queryOne<any>(
      `SELECT * FROM data_collection_configs WHERE id = $1`,
      [configId]
    );

    if (!config) {
      throw new Error("수집 설정을 찾을 수 없습니다.");
    }

    if (!config.is_active) {
      throw new Error("비활성화된 수집 설정입니다.");
    }

    // 수집 작업 기록 생성
    const job = await queryOne<any>(
      `INSERT INTO data_collection_jobs 
       (config_id, job_status, started_at, created_date)
       VALUES ($1, $2, NOW(), NOW())
       RETURNING *`,
      [configId, "running"]
    );

    // 실제 수집 작업 실행 로직은 여기에 구현
    // 현재는 시뮬레이션으로 처리
    setTimeout(async () => {
      try {
        // 수집 작업 시뮬레이션
        await new Promise((resolve) => setTimeout(resolve, 3000));

        const recordsCollected = Math.floor(Math.random() * 1000) + 100;

        await query(
          `UPDATE data_collection_jobs 
           SET job_status = $1, completed_at = NOW(), records_processed = $2
           WHERE id = $3`,
          ["completed", recordsCollected, job.id]
        );
      } catch (error) {
        await query(
          `UPDATE data_collection_jobs 
           SET job_status = $1, completed_at = NOW(), error_message = $2
           WHERE id = $3`,
          [
            "failed",
            error instanceof Error ? error.message : "알 수 없는 오류",
            job.id,
          ]
        );
      }
    }, 0);

    return job as CollectionJob;
  }

  /**
   * 수집 작업 목록 조회
   */
  static async getCollectionJobs(configId?: number): Promise<CollectionJob[]> {
    let sql = `
      SELECT j.*, c.config_name, c.collection_type 
      FROM data_collection_jobs j
      LEFT JOIN data_collection_configs c ON j.config_id = c.id
    `;
    const values: any[] = [];

    if (configId) {
      sql += ` WHERE j.config_id = $1`;
      values.push(configId);
    }

    sql += ` ORDER BY j.started_at DESC`;

    const jobs = await query<any>(sql, values);

    return jobs as CollectionJob[];
  }

  /**
   * 수집 이력 조회
   */
  static async getCollectionHistory(
    configId: number
  ): Promise<CollectionHistory[]> {
    const history = await query<any>(
      `SELECT * FROM data_collection_jobs 
       WHERE config_id = $1 
       ORDER BY started_at DESC 
       LIMIT 50`,
      [configId]
    );

    return history.map((item: any) => ({
      id: item.id,
      config_id: item.config_id,
      status: item.job_status,
      collection_date: item.started_at,
      started_at: item.started_at,
      completed_at: item.completed_at,
      execution_time_ms:
        item.completed_at && item.started_at
          ? new Date(item.completed_at).getTime() -
            new Date(item.started_at).getTime()
          : null,
      records_collected: item.records_processed || 0,
      result_message: `${item.records_processed || 0}개의 레코드가 처리되었습니다.`,
      error_message: item.error_message,
    })) as CollectionHistory[];
  }
}
