import 'constants.dart';
import 'models.dart';
/// 键识别 + 共振与纠缠判断
/// © 2026 Jason Li. All rights reserved.

class KeyAnalyzer {
  static List<KeyRelation> identify(BaziChart chart) {
    final keys = <KeyRelation>[];
    final stems = chart.allStems;
    final branches = chart.allBranches;
    final labels = ['年', '月', '日', '时'];

    // 天干五合
    for (var i = 0; i < stems.length; i++) {
      for (var j = i + 1; j < stems.length; j++) {
        final el = _stemCombine(stems[i], stems[j]);
        if (el != null) {
          keys.add(KeyRelation(
            type: '天干五合',
            members: [stems[i], stems[j]],
            transformedElement: el,
            detail: '${labels[i]}${stems[i]}+${labels[j]}${stems[j]}合$el',
            baseMultiplier: 2.0,
          ));
        }
      }
    }

    // 地支六合
    for (var i = 0; i < branches.length; i++) {
      for (var j = i + 1; j < branches.length; j++) {
        final el = _pairLookup(branchSixHarmony, branches[i], branches[j]);
        if (el != null) {
          final dist = _distanceFactor(i, j);
          keys.add(KeyRelation(
            type: '地支六合',
            members: [branches[i], branches[j]],
            transformedElement: el,
            detail:
                '${labels[i]}${branches[i]}+${labels[j]}${branches[j]}合$el (E×${dist.toStringAsFixed(2)})',
            baseMultiplier: 2.0 * dist,
          ));
        }
      }
    }

    // 地支六冲
    for (var i = 0; i < branches.length; i++) {
      for (var j = i + 1; j < branches.length; j++) {
        if (_isPair(branchClashPairs, branches[i], branches[j])) {
          final dist = _distanceFactor(i, j);
          final mult = dist >= 1.0 ? 6.0 : (dist >= 0.5 ? 4.0 : 4.0);
          keys.add(KeyRelation(
            type: '地支六冲',
            members: [branches[i], branches[j]],
            detail:
                '${labels[i]}${branches[i]}冲${labels[j]}${branches[j]}',
            baseMultiplier: mult,
          ));
        }
      }
    }

    // 地支六害
    for (var i = 0; i < branches.length; i++) {
      for (var j = i + 1; j < branches.length; j++) {
        if (_isPair(branchHarmPairs, branches[i], branches[j])) {
          keys.add(KeyRelation(
            type: '地支六害',
            members: [branches[i], branches[j]],
            detail:
                '${labels[i]}${branches[i]}害${labels[j]}${branches[j]}',
            baseMultiplier: 2.0,
          ));
        }
      }
    }

    // 地支六破
    for (var i = 0; i < branches.length; i++) {
      for (var j = i + 1; j < branches.length; j++) {
        if (_isPair(branchBreakPairs, branches[i], branches[j])) {
          keys.add(KeyRelation(
            type: '地支六破',
            members: [branches[i], branches[j]],
            detail:
                '${labels[i]}${branches[i]}破${labels[j]}${branches[j]}',
            baseMultiplier: 2.0,
          ));
        }
      }
    }

    // 三合
    for (final entry in branchTripleHarmony.entries) {
      final present =
          entry.value.where((b) => branches.contains(b)).toSet().toList();
      if (present.length >= 2) {
        keys.add(KeyRelation(
          type: '地支三合',
          members: present,
          transformedElement: entry.key,
          detail:
              '${present.join("")}合${entry.key}${present.length == 3 ? "（成局）" : "（半合）"}',
          baseMultiplier: present.length == 3 ? 3.0 : 2.5,
        ));
      }
    }

    // 三会
    for (final entry in branchTripleMeeting.entries) {
      final present =
          entry.value.where((b) => branches.contains(b)).toSet().toList();
      if (present.length >= 2) {
        keys.add(KeyRelation(
          type: '地支三会',
          members: present,
          transformedElement: entry.key,
          detail:
              '${present.join("")}会${entry.key}${present.length == 3 ? "（成局）" : ""}',
          baseMultiplier: present.length == 3 ? 3.0 : 2.5,
        ));
      }
    }

    // 三刑
    for (final entry in branchPunishments.entries) {
      final needed = entry.value;
      final present = needed.where((b) => branches.contains(b)).toList();
      if (needed.length == 2 && present.length == 2) {
        keys.add(KeyRelation(
          type: '地支三刑',
          members: present,
          detail: '${entry.key}:${present.join("")}',
          baseMultiplier: 2.5,
        ));
      } else if (needed.length == 3 && present.length >= 2) {
        keys.add(KeyRelation(
          type: '地支三刑',
          members: present,
          detail: '${entry.key}:${present.join("")}',
          baseMultiplier: present.length == 3 ? 3.0 : 2.5,
        ));
      }
    }

    // 同字共振
    final stemCount = <String, int>{};
    for (final s in stems) {
      stemCount[s] = (stemCount[s] ?? 0) + 1;
    }
    for (final e in stemCount.entries) {
      if (e.value >= 2) {
        keys.add(KeyRelation(
          type: '同字共振',
          members: List.filled(e.value, e.key),
          detail: '天干${e.key}×${e.value}',
          baseMultiplier: 2.0,
        ));
      }
    }
    final branchCount = <String, int>{};
    for (final b in branches) {
      branchCount[b] = (branchCount[b] ?? 0) + 1;
    }
    for (final e in branchCount.entries) {
      if (e.value >= 2) {
        keys.add(KeyRelation(
          type: '同字共振',
          members: List.filled(e.value, e.key),
          detail: '地支${e.key}×${e.value}',
          baseMultiplier: 2.0,
        ));
      }
    }

    // 同行共振（同五行）
    final elStems = <String, List<String>>{};
    for (final s in stems) {
      final el = GanZhi.stemElement[s]!;
      elStems.putIfAbsent(el, () => []).add(s);
    }
    for (final e in elStems.entries) {
      if (e.value.length >= 2) {
        keys.add(KeyRelation(
          type: '同行共振',
          members: e.value,
          transformedElement: e.key,
          detail: '天干同行${e.key}:${e.value.join("")}',
          baseMultiplier: 2.0,
        ));
      }
    }

    // 生克（邻柱 / 同柱）
    for (var i = 0; i < 4; i++) {
      final s = stems[i];
      final b = branches[i];
      final se = GanZhi.stemElement[s]!;
      final be = GanZhi.branchElement[b]!;
      final rel = _shengKe(se, be);
      if (rel != null) {
        keys.add(KeyRelation(
          type: rel,
          members: [s, b],
          detail: '${labels[i]}柱 $s$b $rel (接触 E=2)',
          baseMultiplier: 2.0,
        ));
      }
    }
    for (var i = 0; i < 3; i++) {
      final a = GanZhi.stemElement[stems[i]]!;
      final b = GanZhi.stemElement[stems[i + 1]]!;
      final rel = _shengKe(a, b);
      if (rel != null) {
        keys.add(KeyRelation(
          type: rel,
          members: [stems[i], stems[i + 1]],
          detail: '${labels[i]}→${labels[i + 1]}天干$rel (渗透 E=1)',
          baseMultiplier: 1.0,
        ));
      }
    }

    return keys;
  }

  static ResonanceResult resonanceAndEntanglement(List<KeyRelation> keys) {
    final resonance = <KeyRelation>[];
    final entanglement = <KeyRelation>[];
    final multipliers = <String, double>{};

    for (final k in keys) {
      if (k.type == '同字共振' ||
          k.type == '同行共振' ||
          k.type.contains('合') ||
          k.type.contains('会') ||
          k.baseMultiplier >= 2.0) {
        resonance.add(k);
        multipliers[k.detail] = k.baseMultiplier.clamp(1.0, 6.0);
      }
      if (k.type == '同行共振') {
        entanglement.add(KeyRelation(
          type: '同行纠缠',
          members: k.members,
          transformedElement: k.transformedElement,
          detail: '${k.detail} → 状态同步，不叠加能量',
          baseMultiplier: 1.0,
        ));
      }
      if (k.type == '地支六冲') {
        entanglement.add(KeyRelation(
          type: '对冲纠缠',
          members: k.members,
          detail: '${k.detail} → 状态同步，方向相反',
          baseMultiplier: 1.0,
        ));
      }
      if (k.type.contains('合') && k.transformedElement != null) {
        entanglement.add(KeyRelation(
          type: '合化纠缠',
          members: k.members,
          transformedElement: k.transformedElement,
          detail: '${k.detail} → 合化后状态同步',
          baseMultiplier: 1.0,
        ));
      }
    }

    return ResonanceResult(
      resonanceKeys: resonance,
      entanglementKeys: entanglement,
      multipliers: multipliers,
    );
  }

  static double _distanceFactor(int i, int j) {
    // a=-1 同柱不适用于两柱；邻柱 a=0 →1; 隔一 a=1 →0.5; 隔二 a=2 →0.25
    final gap = (j - i).abs();
    if (gap == 1) return 1.0;
    if (gap == 2) return 0.5;
    if (gap == 3) return 0.25;
    return 1.0;
  }

  static String? _stemCombine(String a, String b) {
    for (final e in stemCombinations.entries) {
      if ((e.key.$1 == a && e.key.$2 == b) ||
          (e.key.$1 == b && e.key.$2 == a)) {
        return e.value;
      }
    }
    return null;
  }

  static String? _pairLookup(
      Map<(String, String), String> table, String a, String b) {
    for (final e in table.entries) {
      if ((e.key.$1 == a && e.key.$2 == b) ||
          (e.key.$1 == b && e.key.$2 == a)) {
        return e.value;
      }
    }
    return null;
  }

  static bool _isPair(List<(String, String)> pairs, String a, String b) {
    for (final p in pairs) {
      if ((p.$1 == a && p.$2 == b) || (p.$1 == b && p.$2 == a)) return true;
    }
    return false;
  }

  static String? _shengKe(String a, String b) {
    const gen = {'木': '火', '火': '土', '土': '金', '金': '水', '水': '木'};
    const ctrl = {'木': '土', '土': '水', '水': '火', '火': '金', '金': '木'};
    if (gen[a] == b) return '生';
    if (ctrl[a] == b) return '克';
    if (gen[b] == a) return '生';
    if (ctrl[b] == a) return '克';
    return null;
  }
}
