// @ts-nocheck
/**
 * 플로우 단계 서비스
 */

import db from "../database/db";
import {
  FlowStep,
  CreateFlowStepRequest,
  UpdateFlowStepRequest,
  FlowConditionGroup,
} from "../types/flow";
import { FlowConditionParser } from "./flowConditionParser";

export class FlowStepService {
  /**
   * 플로우 단계 생성
   */
  async create(request: CreateFlowStepRequest): Promise<FlowStep> {
    // 조건 검증
    if (request.conditionJson) {
      FlowConditionParser.validateConditionGroup(request.conditionJson);
    }

    const query = `
      INSERT INTO flow_step (
        flow_definition_id, step_name, step_order, table_name, condition_json, 
        color, position_x, position_y, move_type, status_column, status_value,
        target_table, field_mappings, required_fields,
        integration_type, integration_config, display_config
      )
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
      RETURNING *
    `;

    const result = await db.query(query, [
      request.flowDefinitionId,
      request.stepName,
      request.stepOrder,
      request.tableName || null,
      request.conditionJson ? JSON.stringify(request.conditionJson) : null,
      request.color || "#3B82F6",
      request.positionX || 0,
      request.positionY || 0,
      request.moveType || null,
      request.statusColumn || null,
      request.statusValue || null,
      request.targetTable || null,
      request.fieldMappings ? JSON.stringify(request.fieldMappings) : null,
      request.requiredFields ? JSON.stringify(request.requiredFields) : null,
      request.integrationType || "internal",
      request.integrationConfig
        ? JSON.stringify(request.integrationConfig)
        : null,
      request.displayConfig ? JSON.stringify(request.displayConfig) : null,
    ]);

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

  /**
   * 특정 플로우의 모든 단계 조회
   */
  async findByFlowId(flowDefinitionId: number): Promise<FlowStep[]> {
    const query = `
      SELECT * FROM flow_step 
      WHERE flow_definition_id = $1 
      ORDER BY step_order ASC
    `;

    const result = await db.query(query, [flowDefinitionId]);
    return result.map(this.mapToFlowStep);
  }

  /**
   * 플로우 단계 단일 조회
   */
  async findById(id: number): Promise<FlowStep | null> {
    const query = "SELECT * FROM flow_step WHERE id = $1";
    const result = await db.query(query, [id]);

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

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

  /**
   * 플로우 단계 수정
   */
  async update(
    id: number,
    request: UpdateFlowStepRequest
  ): Promise<FlowStep | null> {
    // 조건 검증
    if (request.conditionJson) {
      FlowConditionParser.validateConditionGroup(request.conditionJson);
    }

    const fields: string[] = [];
    const params: any[] = [];
    let paramIndex = 1;

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

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

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

    if (request.conditionJson !== undefined) {
      fields.push(`condition_json = $${paramIndex}`);
      params.push(
        request.conditionJson ? JSON.stringify(request.conditionJson) : null
      );
      paramIndex++;
    }

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

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

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

    // 하이브리드 플로우 필드
    if (request.moveType !== undefined) {
      fields.push(`move_type = $${paramIndex}`);
      params.push(request.moveType);
      paramIndex++;
    }

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

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

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

    if (request.fieldMappings !== undefined) {
      fields.push(`field_mappings = $${paramIndex}`);
      params.push(
        request.fieldMappings ? JSON.stringify(request.fieldMappings) : null
      );
      paramIndex++;
    }

    if (request.requiredFields !== undefined) {
      fields.push(`required_fields = $${paramIndex}`);
      params.push(
        request.requiredFields ? JSON.stringify(request.requiredFields) : null
      );
      paramIndex++;
    }

    // 외부 연동 필드
    if (request.integrationType !== undefined) {
      fields.push(`integration_type = $${paramIndex}`);
      params.push(request.integrationType);
      paramIndex++;
    }

    if (request.integrationConfig !== undefined) {
      fields.push(`integration_config = $${paramIndex}`);
      params.push(
        request.integrationConfig
          ? JSON.stringify(request.integrationConfig)
          : null
      );
      paramIndex++;
    }

    // 표시 설정 (displayConfig)
    if (request.displayConfig !== undefined) {
      fields.push(`display_config = $${paramIndex}`);
      params.push(
        request.displayConfig ? JSON.stringify(request.displayConfig) : null
      );
      paramIndex++;
    }

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

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

    const query = `
      UPDATE flow_step
      SET ${fields.join(", ")}
      WHERE id = $${paramIndex}
      RETURNING *
    `;
    params.push(id);

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

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

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

  /**
   * 플로우 단계 삭제
   */
  async delete(id: number): Promise<boolean> {
    const query = "DELETE FROM flow_step WHERE id = $1 RETURNING id";
    const result = await db.query(query, [id]);
    return result.length > 0;
  }

  /**
   * 단계 순서 재정렬
   */
  async reorder(
    flowDefinitionId: number,
    stepOrders: { id: number; order: number }[]
  ): Promise<void> {
    await db.transaction(async (client) => {
      for (const { id, order } of stepOrders) {
        await client.query(
          "UPDATE flow_step SET step_order = $1, updated_at = NOW() WHERE id = $2 AND flow_definition_id = $3",
          [order, id, flowDefinitionId]
        );
      }
    });
  }

  /**
   * DB 행을 FlowStep 객체로 변환
   */
  private mapToFlowStep(row: any): FlowStep {
    // JSONB 필드는 pg 라이브러리가 자동으로 파싱해줌
    const displayConfig = row.display_config;

    return {
      id: row.id,
      flowDefinitionId: row.flow_definition_id,
      stepName: row.step_name,
      stepOrder: row.step_order,
      tableName: row.table_name || undefined,
      conditionJson: row.condition_json as FlowConditionGroup | undefined,
      color: row.color,
      positionX: row.position_x,
      positionY: row.position_y,
      // 하이브리드 플로우 지원 필드
      moveType: row.move_type || undefined,
      statusColumn: row.status_column || undefined,
      statusValue: row.status_value || undefined,
      targetTable: row.target_table || undefined,
      fieldMappings: row.field_mappings || undefined,
      requiredFields: row.required_fields || undefined,
      // 외부 연동 필드
      integrationType: row.integration_type || "internal",
      integrationConfig: row.integration_config || undefined,
      // 표시 설정
      displayConfig: displayConfig || undefined,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
    };
  }
}
