/**
 * 조건부 연쇄 (Conditional Cascading) 컨트롤러
 * 특정 필드 값에 따라 드롭다운 옵션을 필터링하는 기능
 */

import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import { query, queryOne } from "../database/db";
import logger from "../utils/logger";

// =====================================================
// 조건부 연쇄 규칙 CRUD
// =====================================================

/**
 * 조건부 연쇄 규칙 목록 조회
 */
export const getConditions = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const companyCode = req.user?.companyCode || "*";
    const { isActive, relationCode, relationType } = req.query;

    let sql = `
      SELECT * FROM cascading_condition
      WHERE 1=1
    `;
    const params: any[] = [];
    let paramIndex = 1;

    // 회사 필터
    if (companyCode !== "*") {
      sql += ` AND company_code = $${paramIndex++}`;
      params.push(companyCode);
    }

    // 활성 상태 필터
    if (isActive) {
      sql += ` AND is_active = $${paramIndex++}`;
      params.push(isActive);
    }

    // 관계 코드 필터
    if (relationCode) {
      sql += ` AND relation_code = $${paramIndex++}`;
      params.push(relationCode);
    }

    // 관계 유형 필터 (RELATION / HIERARCHY)
    if (relationType) {
      sql += ` AND relation_type = $${paramIndex++}`;
      params.push(relationType);
    }

    sql += ` ORDER BY relation_code, priority, condition_name`;

    const result = await query(sql, params);

    logger.info("조건부 연쇄 규칙 목록 조회", {
      count: result.length,
      companyCode,
    });

    res.json({
      success: true,
      data: result,
    });
  } catch (error: any) {
    console.error("조건부 연쇄 규칙 목록 조회 실패:", error);
    logger.error("조건부 연쇄 규칙 목록 조회 실패", {
      error: error.message,
      stack: error.stack,
    });
    res.status(500).json({
      success: false,
      message: "조건부 연쇄 규칙 목록 조회에 실패했습니다.",
      error: error.message,
    });
  }
};

/**
 * 조건부 연쇄 규칙 상세 조회
 */
export const getConditionDetail = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { conditionId } = req.params;
    const companyCode = req.user?.companyCode || "*";

    let sql = `SELECT * FROM cascading_condition WHERE condition_id = $1`;
    const params: any[] = [Number(conditionId)];

    if (companyCode !== "*") {
      sql += ` AND company_code = $2`;
      params.push(companyCode);
    }

    const result = await queryOne(sql, params);

    if (!result) {
      return res.status(404).json({
        success: false,
        message: "조건부 연쇄 규칙을 찾을 수 없습니다.",
      });
    }

    logger.info("조건부 연쇄 규칙 상세 조회", { conditionId, companyCode });

    res.json({
      success: true,
      data: result,
    });
  } catch (error: any) {
    logger.error("조건부 연쇄 규칙 상세 조회 실패", { error: error.message });
    res.status(500).json({
      success: false,
      message: "조건부 연쇄 규칙 상세 조회에 실패했습니다.",
      error: error.message,
    });
  }
};

/**
 * 조건부 연쇄 규칙 생성
 */
export const createCondition = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const companyCode = req.user?.companyCode || "*";
    const {
      relationType = "RELATION",
      relationCode,
      conditionName,
      conditionField,
      conditionOperator = "EQ",
      conditionValue,
      filterColumn,
      filterValues,
      priority = 0,
    } = req.body;

    // 필수 필드 검증
    if (
      !relationCode ||
      !conditionName ||
      !conditionField ||
      !conditionValue ||
      !filterColumn ||
      !filterValues
    ) {
      return res.status(400).json({
        success: false,
        message:
          "필수 필드가 누락되었습니다. (relationCode, conditionName, conditionField, conditionValue, filterColumn, filterValues)",
      });
    }

    const insertSql = `
      INSERT INTO cascading_condition (
        relation_type, relation_code, condition_name,
        condition_field, condition_operator, condition_value,
        filter_column, filter_values, priority,
        company_code, is_active, created_date
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, 'Y', CURRENT_TIMESTAMP)
      RETURNING *
    `;

    const result = await queryOne(insertSql, [
      relationType,
      relationCode,
      conditionName,
      conditionField,
      conditionOperator,
      conditionValue,
      filterColumn,
      filterValues,
      priority,
      companyCode,
    ]);

    logger.info("조건부 연쇄 규칙 생성", {
      conditionId: result?.condition_id,
      relationCode,
      companyCode,
    });

    res.status(201).json({
      success: true,
      message: "조건부 연쇄 규칙이 생성되었습니다.",
      data: result,
    });
  } catch (error: any) {
    logger.error("조건부 연쇄 규칙 생성 실패", { error: error.message });
    res.status(500).json({
      success: false,
      message: "조건부 연쇄 규칙 생성에 실패했습니다.",
      error: error.message,
    });
  }
};

/**
 * 조건부 연쇄 규칙 수정
 */
export const updateCondition = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { conditionId } = req.params;
    const companyCode = req.user?.companyCode || "*";
    const {
      conditionName,
      conditionField,
      conditionOperator,
      conditionValue,
      filterColumn,
      filterValues,
      priority,
      isActive,
    } = req.body;

    // 기존 규칙 확인
    let checkSql = `SELECT * FROM cascading_condition WHERE condition_id = $1`;
    const checkParams: any[] = [Number(conditionId)];

    if (companyCode !== "*") {
      checkSql += ` AND company_code = $2`;
      checkParams.push(companyCode);
    }

    const existing = await queryOne(checkSql, checkParams);

    if (!existing) {
      return res.status(404).json({
        success: false,
        message: "조건부 연쇄 규칙을 찾을 수 없습니다.",
      });
    }

    const updateSql = `
      UPDATE cascading_condition SET
        condition_name = COALESCE($1, condition_name),
        condition_field = COALESCE($2, condition_field),
        condition_operator = COALESCE($3, condition_operator),
        condition_value = COALESCE($4, condition_value),
        filter_column = COALESCE($5, filter_column),
        filter_values = COALESCE($6, filter_values),
        priority = COALESCE($7, priority),
        is_active = COALESCE($8, is_active),
        updated_date = CURRENT_TIMESTAMP
      WHERE condition_id = $9
      RETURNING *
    `;

    const result = await queryOne(updateSql, [
      conditionName,
      conditionField,
      conditionOperator,
      conditionValue,
      filterColumn,
      filterValues,
      priority,
      isActive,
      Number(conditionId),
    ]);

    logger.info("조건부 연쇄 규칙 수정", { conditionId, companyCode });

    res.json({
      success: true,
      message: "조건부 연쇄 규칙이 수정되었습니다.",
      data: result,
    });
  } catch (error: any) {
    logger.error("조건부 연쇄 규칙 수정 실패", { error: error.message });
    res.status(500).json({
      success: false,
      message: "조건부 연쇄 규칙 수정에 실패했습니다.",
      error: error.message,
    });
  }
};

/**
 * 조건부 연쇄 규칙 삭제
 */
export const deleteCondition = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { conditionId } = req.params;
    const companyCode = req.user?.companyCode || "*";

    let deleteSql = `DELETE FROM cascading_condition WHERE condition_id = $1`;
    const deleteParams: any[] = [Number(conditionId)];

    if (companyCode !== "*") {
      deleteSql += ` AND company_code = $2`;
      deleteParams.push(companyCode);
    }

    deleteSql += ` RETURNING condition_id`;

    const result = await queryOne(deleteSql, deleteParams);

    if (!result) {
      return res.status(404).json({
        success: false,
        message: "조건부 연쇄 규칙을 찾을 수 없습니다.",
      });
    }

    logger.info("조건부 연쇄 규칙 삭제", { conditionId, companyCode });

    res.json({
      success: true,
      message: "조건부 연쇄 규칙이 삭제되었습니다.",
    });
  } catch (error: any) {
    logger.error("조건부 연쇄 규칙 삭제 실패", { error: error.message });
    res.status(500).json({
      success: false,
      message: "조건부 연쇄 규칙 삭제에 실패했습니다.",
      error: error.message,
    });
  }
};

// =====================================================
// 조건부 필터링 적용 API (실제 사용)
// =====================================================

/**
 * 조건에 따른 필터링된 옵션 조회
 * 특정 관계 코드에 대해 조건 필드 값에 따라 필터링된 옵션 반환
 */
export const getFilteredOptions = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { relationCode } = req.params;
    const { conditionFieldValue, parentValue } = req.query;
    const companyCode = req.user?.companyCode || "*";

    // 1. 기본 연쇄 관계 정보 조회
    let relationSql = `SELECT * FROM cascading_relation WHERE relation_code = $1 AND is_active = 'Y'`;
    const relationParams: any[] = [relationCode];

    if (companyCode !== "*") {
      relationSql += ` AND company_code = $2`;
      relationParams.push(companyCode);
    }

    const relation = await queryOne(relationSql, relationParams);

    if (!relation) {
      return res.status(404).json({
        success: false,
        message: "연쇄 관계를 찾을 수 없습니다.",
      });
    }

    // 2. 해당 관계에 적용되는 조건 규칙 조회
    let conditionSql = `
      SELECT * FROM cascading_condition 
      WHERE relation_code = $1 AND is_active = 'Y'
    `;
    const conditionParams: any[] = [relationCode];
    let conditionParamIndex = 2;

    if (companyCode !== "*") {
      conditionSql += ` AND company_code = $${conditionParamIndex++}`;
      conditionParams.push(companyCode);
    }

    conditionSql += ` ORDER BY priority DESC`;

    const conditions = await query(conditionSql, conditionParams);

    // 3. 조건에 맞는 규칙 찾기
    let matchedCondition: any = null;

    if (conditionFieldValue) {
      for (const cond of conditions) {
        const isMatch = evaluateCondition(
          conditionFieldValue as string,
          cond.condition_operator,
          cond.condition_value
        );

        if (isMatch) {
          matchedCondition = cond;
          break; // 우선순위가 높은 첫 번째 매칭 규칙 사용
        }
      }
    }

    // 4. 옵션 조회 쿼리 생성
    let optionsSql = `
      SELECT 
        ${relation.child_value_column} as value,
        ${relation.child_label_column} as label
      FROM ${relation.child_table}
      WHERE 1=1
    `;
    const optionsParams: any[] = [];
    let optionsParamIndex = 1;

    // 부모 값 필터 (기본 연쇄)
    if (parentValue) {
      optionsSql += ` AND ${relation.child_filter_column} = $${optionsParamIndex++}`;
      optionsParams.push(parentValue);
    }

    // 조건부 필터 적용
    if (matchedCondition) {
      const filterValues = matchedCondition.filter_values
        .split(",")
        .map((v: string) => v.trim());
      const placeholders = filterValues
        .map((_: any, i: number) => `$${optionsParamIndex + i}`)
        .join(",");
      optionsSql += ` AND ${matchedCondition.filter_column} IN (${placeholders})`;
      optionsParams.push(...filterValues);
      optionsParamIndex += filterValues.length;
    }

    // 멀티테넌시 필터
    if (companyCode !== "*") {
      const columnCheck = await queryOne(
        `SELECT column_name FROM information_schema.columns 
         WHERE table_name = $1 AND column_name = 'company_code'`,
        [relation.child_table]
      );

      if (columnCheck) {
        optionsSql += ` AND company_code = $${optionsParamIndex++}`;
        optionsParams.push(companyCode);
      }
    }

    // 정렬
    if (relation.child_order_column) {
      optionsSql += ` ORDER BY ${relation.child_order_column} ${relation.child_order_direction || "ASC"}`;
    } else {
      optionsSql += ` ORDER BY ${relation.child_label_column}`;
    }

    const optionsResult = await query(optionsSql, optionsParams);

    logger.info("조건부 필터링 옵션 조회", {
      relationCode,
      conditionFieldValue,
      parentValue,
      matchedCondition: matchedCondition?.condition_name,
      optionCount: optionsResult.length,
    });

    res.json({
      success: true,
      data: optionsResult,
      appliedCondition: matchedCondition
        ? {
            conditionId: matchedCondition.condition_id,
            conditionName: matchedCondition.condition_name,
          }
        : null,
    });
  } catch (error: any) {
    logger.error("조건부 필터링 옵션 조회 실패", { error: error.message });
    res.status(500).json({
      success: false,
      message: "조건부 필터링 옵션 조회에 실패했습니다.",
      error: error.message,
    });
  }
};

/**
 * 조건 평가 함수
 */
function evaluateCondition(
  actualValue: string,
  operator: string,
  expectedValue: string
): boolean {
  const actual = actualValue.toLowerCase().trim();
  const expected = expectedValue.toLowerCase().trim();

  switch (operator.toUpperCase()) {
    case "EQ":
    case "=":
    case "EQUALS":
      return actual === expected;

    case "NEQ":
    case "!=":
    case "<>":
    case "NOT_EQUALS":
      return actual !== expected;

    case "CONTAINS":
    case "LIKE":
      return actual.includes(expected);

    case "NOT_CONTAINS":
    case "NOT_LIKE":
      return !actual.includes(expected);

    case "STARTS_WITH":
      return actual.startsWith(expected);

    case "ENDS_WITH":
      return actual.endsWith(expected);

    case "IN":
      const inValues = expected.split(",").map((v) => v.trim());
      return inValues.includes(actual);

    case "NOT_IN":
      const notInValues = expected.split(",").map((v) => v.trim());
      return !notInValues.includes(actual);

    case "GT":
    case ">":
      return parseFloat(actual) > parseFloat(expected);

    case "GTE":
    case ">=":
      return parseFloat(actual) >= parseFloat(expected);

    case "LT":
    case "<":
      return parseFloat(actual) < parseFloat(expected);

    case "LTE":
    case "<=":
      return parseFloat(actual) <= parseFloat(expected);

    case "IS_NULL":
    case "NULL":
      return actual === "" || actual === "null" || actual === "undefined";

    case "IS_NOT_NULL":
    case "NOT_NULL":
      return actual !== "" && actual !== "null" && actual !== "undefined";

    default:
      logger.warn(`알 수 없는 연산자: ${operator}`);
      return false;
  }
}
