// @ts-nocheck
/**
 * 플로우 정의 서비스
 */

import db from "../database/db";
import {
  FlowDefinition,
  CreateFlowDefinitionRequest,
  UpdateFlowDefinitionRequest,
} from "../types/flow";

export class FlowDefinitionService {
  /**
   * 플로우 정의 생성
   */
  async create(
    request: CreateFlowDefinitionRequest,
    userId: string,
    userCompanyCode?: string
  ): Promise<FlowDefinition> {
    // 클라이언트 입력(request.companyCode) 무시 - 인증된 사용자의 회사 코드만 사용
    const companyCode = userCompanyCode || "*";

    console.log("🔥 flowDefinitionService.create called with:", {
      name: request.name,
      description: request.description,
      tableName: request.tableName,
      dbSourceType: request.dbSourceType,
      dbConnectionId: request.dbConnectionId,
      restApiConnectionId: request.restApiConnectionId,
      restApiEndpoint: request.restApiEndpoint,
      restApiJsonPath: request.restApiJsonPath,
      restApiConnections: request.restApiConnections,
      companyCode,
      userId,
    });

    const query = `
      INSERT INTO flow_definition (
        name, description, table_name, db_source_type, db_connection_id, 
        rest_api_connection_id, rest_api_endpoint, rest_api_json_path,
        rest_api_connections, company_code, created_by
      )
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
      RETURNING *
    `;

    const values = [
      request.name,
      request.description || null,
      request.tableName || null,
      request.dbSourceType || "internal",
      request.dbConnectionId || null,
      request.restApiConnectionId || null,
      request.restApiEndpoint || null,
      request.restApiJsonPath || "response",
      request.restApiConnections ? JSON.stringify(request.restApiConnections) : null,
      companyCode,
      userId,
    ];

    console.log("💾 Executing INSERT with values:", values);

    const result = await db.query(query, values);

    return this.mapToFlowDefinition(result[0]);
  }

  /**
   * 플로우 정의 목록 조회
   */
  async findAll(
    tableName?: string,
    isActive?: boolean,
    companyCode?: string
  ): Promise<FlowDefinition[]> {
    console.log("🔍 flowDefinitionService.findAll called with:", {
      tableName,
      isActive,
      companyCode,
    });

    let query = "SELECT * FROM flow_definition WHERE 1=1";
    const params: any[] = [];
    let paramIndex = 1;

    // 회사 코드 필터링
    if (companyCode && companyCode !== "*") {
      query += ` AND company_code = $${paramIndex}`;
      params.push(companyCode);
      paramIndex++;
      console.log(`✅ Company filter applied: company_code = ${companyCode}`);
    } else {
      console.log(`⚠️ No company filter (companyCode: ${companyCode})`);
    }

    if (tableName) {
      query += ` AND table_name = $${paramIndex}`;
      params.push(tableName);
      paramIndex++;
    }

    if (isActive !== undefined) {
      query += ` AND is_active = $${paramIndex}`;
      params.push(isActive);
      paramIndex++;
    }

    query += " ORDER BY created_at DESC";

    console.log("📋 Final query:", query);
    console.log("📋 Query params:", params);

    const result = await db.query(query, params);
    console.log(`📊 Found ${result.length} flow definitions`);
    return result.map(this.mapToFlowDefinition);
  }

  /**
   * 플로우 정의 단일 조회
   * companyCode가 전달되면 해당 회사 소유 플로우만 반환
   */
  async findById(id: number, companyCode?: string): Promise<FlowDefinition | null> {
    let query: string;
    let params: any[];

    if (companyCode && companyCode !== "*") {
      query = "SELECT * FROM flow_definition WHERE id = $1 AND company_code = $2";
      params = [id, companyCode];
    } else {
      query = "SELECT * FROM flow_definition WHERE id = $1";
      params = [id];
    }

    const result = await db.query(query, params);

    if (result.length === 0) {
      return null;
    }

    return this.mapToFlowDefinition(result[0]);
  }

  /**
   * 플로우 정의 수정
   * companyCode가 전달되면 해당 회사 소유 플로우만 수정 가능
   */
  async update(
    id: number,
    request: UpdateFlowDefinitionRequest,
    companyCode?: string
  ): Promise<FlowDefinition | null> {
    const fields: string[] = [];
    const params: any[] = [];
    let paramIndex = 1;

    if (request.name !== undefined) {
      fields.push(`name = $${paramIndex}`);
      params.push(request.name);
      paramIndex++;
    }

    if (request.description !== undefined) {
      fields.push(`description = $${paramIndex}`);
      params.push(request.description);
      paramIndex++;
    }

    if (request.isActive !== undefined) {
      fields.push(`is_active = $${paramIndex}`);
      params.push(request.isActive);
      paramIndex++;
    }

    if (fields.length === 0) {
      return this.findById(id, companyCode);
    }

    fields.push(`updated_at = NOW()`);

    let whereClause = `WHERE id = $${paramIndex}`;
    params.push(id);
    paramIndex++;

    if (companyCode && companyCode !== "*") {
      whereClause += ` AND company_code = $${paramIndex}`;
      params.push(companyCode);
      paramIndex++;
    }

    const query = `
      UPDATE flow_definition
      SET ${fields.join(", ")}
      ${whereClause}
      RETURNING *
    `;

    const result = await db.query(query, params);

    if (result.length === 0) {
      return null;
    }

    return this.mapToFlowDefinition(result[0]);
  }

  /**
   * 플로우 정의 삭제
   * companyCode가 전달되면 해당 회사 소유 플로우만 삭제 가능
   */
  async delete(id: number, companyCode?: string): Promise<boolean> {
    let query: string;
    let params: any[];

    if (companyCode && companyCode !== "*") {
      query = "DELETE FROM flow_definition WHERE id = $1 AND company_code = $2 RETURNING id";
      params = [id, companyCode];
    } else {
      query = "DELETE FROM flow_definition WHERE id = $1 RETURNING id";
      params = [id];
    }

    const result = await db.query(query, params);
    return result.length > 0;
  }

  /**
   * 테이블 존재 여부 확인
   */
  async checkTableExists(tableName: string): Promise<boolean> {
    const query = `
      SELECT EXISTS (
        SELECT FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = $1
      ) as exists
    `;

    const result = await db.query(query, [tableName]);
    return result[0].exists;
  }

  /**
   * DB 행을 FlowDefinition 객체로 변환
   */
  private mapToFlowDefinition(row: any): FlowDefinition {
    // rest_api_connections 파싱 (JSONB → 배열)
    let restApiConnections = undefined;
    if (row.rest_api_connections) {
      try {
        restApiConnections = typeof row.rest_api_connections === 'string' 
          ? JSON.parse(row.rest_api_connections) 
          : row.rest_api_connections;
      } catch (e) {
        console.warn("Failed to parse rest_api_connections:", e);
        restApiConnections = [];
      }
    }

    return {
      id: row.id,
      name: row.name,
      description: row.description,
      tableName: row.table_name,
      dbSourceType: row.db_source_type || "internal",
      dbConnectionId: row.db_connection_id,
      // REST API 관련 필드 (단일)
      restApiConnectionId: row.rest_api_connection_id,
      restApiEndpoint: row.rest_api_endpoint,
      restApiJsonPath: row.rest_api_json_path,
      // 다중 REST API 관련 필드
      restApiConnections: restApiConnections,
      companyCode: row.company_code || "*",
      isActive: row.is_active,
      createdBy: row.created_by,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
    };
  }
}
