/**
 * 조건부 서식 유틸리티
 * 셀 값에 따른 스타일 계산
 */

import { ConditionalFormatRule } from "../types";

// ==================== 타입 ====================

export interface CellFormatStyle {
  backgroundColor?: string;
  textColor?: string;
  fontWeight?: string;
  dataBarWidth?: number; // 0-100%
  dataBarColor?: string;
  icon?: string; // 이모지 또는 아이콘 이름
}

// ==================== 색상 유틸리티 ====================

/**
 * HEX 색상을 RGB로 변환
 */
function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result
    ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16),
      }
    : null;
}

/**
 * RGB를 HEX로 변환
 */
function rgbToHex(r: number, g: number, b: number): string {
  return (
    "#" +
    [r, g, b]
      .map((x) => {
        const hex = Math.round(x).toString(16);
        return hex.length === 1 ? "0" + hex : hex;
      })
      .join("")
  );
}

/**
 * 두 색상 사이의 보간
 */
function interpolateColor(
  color1: string,
  color2: string,
  factor: number
): string {
  const rgb1 = hexToRgb(color1);
  const rgb2 = hexToRgb(color2);

  if (!rgb1 || !rgb2) return color1;

  const r = rgb1.r + (rgb2.r - rgb1.r) * factor;
  const g = rgb1.g + (rgb2.g - rgb1.g) * factor;
  const b = rgb1.b + (rgb2.b - rgb1.b) * factor;

  return rgbToHex(r, g, b);
}

// ==================== 조건부 서식 계산 ====================

/**
 * Color Scale 스타일 계산
 */
function applyColorScale(
  value: number,
  minValue: number,
  maxValue: number,
  rule: ConditionalFormatRule
): CellFormatStyle {
  if (!rule.colorScale) return {};

  const { minColor, midColor, maxColor } = rule.colorScale;
  const range = maxValue - minValue;

  if (range === 0) {
    return { backgroundColor: minColor };
  }

  const normalizedValue = (value - minValue) / range;

  let backgroundColor: string;

  if (midColor) {
    // 3색 그라데이션
    if (normalizedValue <= 0.5) {
      backgroundColor = interpolateColor(minColor, midColor, normalizedValue * 2);
    } else {
      backgroundColor = interpolateColor(midColor, maxColor, (normalizedValue - 0.5) * 2);
    }
  } else {
    // 2색 그라데이션
    backgroundColor = interpolateColor(minColor, maxColor, normalizedValue);
  }

  // 배경색에 따른 텍스트 색상 결정
  const rgb = hexToRgb(backgroundColor);
  const textColor =
    rgb && rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114 > 186
      ? "#000000"
      : "#ffffff";

  return { backgroundColor, textColor };
}

/**
 * Data Bar 스타일 계산
 */
function applyDataBar(
  value: number,
  minValue: number,
  maxValue: number,
  rule: ConditionalFormatRule
): CellFormatStyle {
  if (!rule.dataBar) return {};

  const { color, minValue: ruleMin, maxValue: ruleMax } = rule.dataBar;

  const min = ruleMin ?? minValue;
  const max = ruleMax ?? maxValue;
  const range = max - min;

  if (range === 0) {
    return { dataBarWidth: 100, dataBarColor: color };
  }

  const width = Math.max(0, Math.min(100, ((value - min) / range) * 100));

  return {
    dataBarWidth: width,
    dataBarColor: color,
  };
}

/**
 * Icon Set 스타일 계산
 */
function applyIconSet(
  value: number,
  minValue: number,
  maxValue: number,
  rule: ConditionalFormatRule
): CellFormatStyle {
  if (!rule.iconSet) return {};

  const { type, thresholds, reverse } = rule.iconSet;
  const range = maxValue - minValue;
  const percentage = range === 0 ? 100 : ((value - minValue) / range) * 100;

  // 아이콘 정의
  const iconSets: Record<string, string[]> = {
    arrows: ["↓", "→", "↑"],
    traffic: ["🔴", "🟡", "🟢"],
    rating: ["⭐", "⭐⭐", "⭐⭐⭐"],
    flags: ["🚩", "🏳️", "🏁"],
  };

  const icons = iconSets[type] || iconSets.arrows;
  const sortedIcons = reverse ? [...icons].reverse() : icons;

  // 임계값에 따른 아이콘 선택
  let iconIndex = 0;
  for (let i = 0; i < thresholds.length; i++) {
    if (percentage >= thresholds[i]) {
      iconIndex = i + 1;
    }
  }
  iconIndex = Math.min(iconIndex, sortedIcons.length - 1);

  return {
    icon: sortedIcons[iconIndex],
  };
}

/**
 * Cell Value 조건 스타일 계산
 */
function applyCellValue(
  value: number,
  rule: ConditionalFormatRule
): CellFormatStyle {
  if (!rule.cellValue) return {};

  const { operator, value1, value2, backgroundColor, textColor, bold } =
    rule.cellValue;

  let matches = false;

  switch (operator) {
    case ">":
      matches = value > value1;
      break;
    case ">=":
      matches = value >= value1;
      break;
    case "<":
      matches = value < value1;
      break;
    case "<=":
      matches = value <= value1;
      break;
    case "=":
      matches = value === value1;
      break;
    case "!=":
      matches = value !== value1;
      break;
    case "between":
      matches = value2 !== undefined && value >= value1 && value <= value2;
      break;
  }

  if (!matches) return {};

  return {
    backgroundColor,
    textColor,
    fontWeight: bold ? "bold" : undefined,
  };
}

// ==================== 메인 함수 ====================

/**
 * 조건부 서식 적용
 */
export function getConditionalStyle(
  value: number | null | undefined,
  field: string,
  rules: ConditionalFormatRule[],
  allValues: number[] // 해당 필드의 모든 값 (min/max 계산용)
): CellFormatStyle {
  if (value === null || value === undefined || isNaN(value)) {
    return {};
  }

  if (!rules || rules.length === 0) {
    return {};
  }

  // min/max 계산
  const numericValues = allValues.filter((v) => !isNaN(v));
  const minValue = Math.min(...numericValues);
  const maxValue = Math.max(...numericValues);

  let resultStyle: CellFormatStyle = {};

  // 해당 필드에 적용되는 규칙 필터링 및 적용
  for (const rule of rules) {
    // 필드 필터 확인
    if (rule.field && rule.field !== field) {
      continue;
    }

    let ruleStyle: CellFormatStyle = {};

    switch (rule.type) {
      case "colorScale":
        ruleStyle = applyColorScale(value, minValue, maxValue, rule);
        break;
      case "dataBar":
        ruleStyle = applyDataBar(value, minValue, maxValue, rule);
        break;
      case "iconSet":
        ruleStyle = applyIconSet(value, minValue, maxValue, rule);
        break;
      case "cellValue":
        ruleStyle = applyCellValue(value, rule);
        break;
    }

    // 스타일 병합 (나중 규칙이 우선)
    resultStyle = { ...resultStyle, ...ruleStyle };
  }

  return resultStyle;
}

/**
 * 조건부 서식 스타일을 React 스타일 객체로 변환
 */
export function formatStyleToReact(
  style: CellFormatStyle
): React.CSSProperties {
  const result: React.CSSProperties = {};

  if (style.backgroundColor) {
    result.backgroundColor = style.backgroundColor;
  }
  if (style.textColor) {
    result.color = style.textColor;
  }
  if (style.fontWeight) {
    result.fontWeight = style.fontWeight as any;
  }

  return result;
}

export default getConditionalStyle;

