/**
 * 조건부 표시 훅
 *
 * display_condition을 기반으로 섹션/필드의 visibility를 결정
 */

'use client';

import { useMemo } from 'react';
import type {
  DynamicFormStructure,
  DynamicFormData,
  DisplayCondition,
  FieldConditionConfig,
  ConditionOperator,
} from '../types';
import type { DynamicFieldValue } from '../types';

/**
 * 조건 연산자 평가
 * operator가 없으면 'equals' (하위호환)
 */
function evaluateCondition(
  currentValue: DynamicFieldValue,
  operator: ConditionOperator,
  expectedValue: string
): boolean {
  const strValue = currentValue !== null && currentValue !== undefined ? String(currentValue) : '';
  const numValue = Number(currentValue);
  const numExpected = Number(expectedValue);

  switch (operator) {
    case 'equals':
      return strValue === expectedValue;
    case 'not_equals':
      return strValue !== expectedValue;
    case 'in': {
      const list = expectedValue.split(',').map(s => s.trim());
      return list.includes(strValue);
    }
    case 'not_in': {
      const list = expectedValue.split(',').map(s => s.trim());
      return !list.includes(strValue);
    }
    case 'greater_than':
      return !isNaN(numValue) && !isNaN(numExpected) && numValue > numExpected;
    case 'less_than':
      return !isNaN(numValue) && !isNaN(numExpected) && numValue < numExpected;
    case 'gte':
      return !isNaN(numValue) && !isNaN(numExpected) && numValue >= numExpected;
    case 'lte':
      return !isNaN(numValue) && !isNaN(numExpected) && numValue <= numExpected;
    case 'contains':
      return strValue.includes(expectedValue);
    default:
      return strValue === expectedValue;
  }
}

interface ConditionalDisplayResult {
  /** 섹션이 표시되어야 하는지 확인 */
  shouldShowSection: (sectionId: number) => boolean;
  /** 필드가 표시되어야 하는지 확인 */
  shouldShowField: (fieldId: number) => boolean;
  /** 조건부 표시 설정이 있는 트리거 필드 목록 */
  triggerFields: Array<{
    fieldKey: string;
    fieldId: number;
    condition: DisplayCondition;
  }>;
}

/**
 * 조건부 표시 훅
 *
 * @param structure - 폼 구조
 * @param formData - 현재 폼 데이터
 * @returns 조건부 표시 관련 함수들
 */
export function useConditionalDisplay(
  structure: DynamicFormStructure | null,
  formData: DynamicFormData
): ConditionalDisplayResult {
  // 조건부 표시 설정이 있는 필드들 수집
  const triggerFields = useMemo(() => {
    if (!structure) return [];

    const triggers: ConditionalDisplayResult['triggerFields'] = [];

    // 모든 섹션의 필드 검사
    structure.sections.forEach((section) => {
      section.fields.forEach((dynamicField) => {
        const field = dynamicField.field;
        if (field.display_condition) {
          const condition = field.display_condition as DisplayCondition;
          triggers.push({
            fieldKey: field.field_key || `field_${field.id}`,
            fieldId: field.id,
            condition,
          });
        }
      });
    });

    // 직접 필드도 검사
    structure.directFields.forEach((dynamicField) => {
      const field = dynamicField.field;
      if (field.display_condition) {
        const condition = field.display_condition as DisplayCondition;
        triggers.push({
          fieldKey: field.field_key || `field_${field.id}`,
          fieldId: field.id,
          condition,
        });
      }
    });

    return triggers;
  }, [structure]);

  // 현재 활성화된 조건들 계산
  const activeConditions = useMemo(() => {
    const activeSectionIds = new Set<string>();
    const activeFieldIds = new Set<string>();

    // 각 트리거 필드의 현재 값 확인
    triggerFields.forEach((trigger) => {
      const currentValue = formData[trigger.fieldKey];
      const condition = trigger.condition;

      // fieldConditions 배열 순회
      if (condition.fieldConditions) {
        condition.fieldConditions.forEach((fc: FieldConditionConfig) => {
          const isMatch = evaluateCondition(currentValue, fc.operator || 'equals', fc.expectedValue);

          if (isMatch) {
            // 일치하면 타겟 섹션/필드 활성화
            if (fc.targetSectionIds) {
              fc.targetSectionIds.forEach((id) => activeSectionIds.add(id));
            }
            if (fc.targetFieldIds) {
              fc.targetFieldIds.forEach((id) => activeFieldIds.add(id));
            }
          }
        });
      }
    });

    return { activeSectionIds, activeFieldIds };
  }, [triggerFields, formData]);

  // 조건부 표시가 적용되는 섹션 ID 목록
  const conditionalSectionIds = useMemo(() => {
    const ids = new Set<string>();

    triggerFields.forEach((trigger) => {
      const condition = trigger.condition;
      if (condition.fieldConditions) {
        condition.fieldConditions.forEach((fc: FieldConditionConfig) => {
          if (fc.targetSectionIds) {
            fc.targetSectionIds.forEach((id) => ids.add(id));
          }
        });
      }
    });

    return ids;
  }, [triggerFields]);

  // 조건부 표시가 적용되는 필드 ID 목록
  const conditionalFieldIds = useMemo(() => {
    const ids = new Set<string>();

    triggerFields.forEach((trigger) => {
      const condition = trigger.condition;
      if (condition.fieldConditions) {
        condition.fieldConditions.forEach((fc: FieldConditionConfig) => {
          if (fc.targetFieldIds) {
            fc.targetFieldIds.forEach((id) => ids.add(id));
          }
        });
      }
    });

    return ids;
  }, [triggerFields]);

  // 섹션 표시 여부 확인
  const shouldShowSection = useMemo(() => {
    return (sectionId: number): boolean => {
      const sectionIdStr = String(sectionId);

      // 이 섹션이 조건부 표시 대상인지 확인
      if (!conditionalSectionIds.has(sectionIdStr)) {
        // 조건부 표시 대상이 아니면 항상 표시
        return true;
      }

      // 조건부 표시 대상이면 활성화된 섹션인지 확인
      return activeConditions.activeSectionIds.has(sectionIdStr);
    };
  }, [conditionalSectionIds, activeConditions]);

  // 필드 표시 여부 확인
  const shouldShowField = useMemo(() => {
    return (fieldId: number): boolean => {
      const fieldIdStr = String(fieldId);

      // 이 필드가 조건부 표시 대상인지 확인
      if (!conditionalFieldIds.has(fieldIdStr)) {
        // 조건부 표시 대상이 아니면 항상 표시
        return true;
      }

      // 조건부 표시 대상이면 활성화된 필드인지 확인
      return activeConditions.activeFieldIds.has(fieldIdStr);
    };
  }, [conditionalFieldIds, activeConditions]);

  return {
    shouldShowSection,
    shouldShowField,
    triggerFields,
  };
}