import 'constants.dart';
import 'chart_engine.dart';
import 'cross_chart.dart';
import 'energy_calculator.dart';
import 'key_analyzer.dart';
import 'liuqin.dart';
import 'models.dart';
/// 判局报告生成 + 531 边界
/// © 2026 Jason Li. All rights reserved.

class ReportGenerator {
  static JudgmentReport generate(BirthInput input, {int? flowYear}) {
    final chart = ChartEngine.build(input);
    return generateFromChart(chart, flowYear: flowYear);
  }

  static JudgmentReport generateFromChart(BaziChart chart, {int? flowYear}) {
    final keys = KeyAnalyzer.identify(chart);
    final resonance = KeyAnalyzer.resonanceAndEntanglement(keys);
    final energy = EnergyCalculator.calculate(chart, keys);
    final liuQin = LiuQinLocator.locate(chart);

    final structure = _structureType(chart, energy);
    final core = keys
        .where((k) => k.baseMultiplier >= 2.5)
        .map((k) => k.detail)
        .take(8)
        .toList();
    final digestion = _digestion(keys);
    final year = flowYear ?? DateTime.now().year;
    final timing = [
      ...PenetrationAnalyzer.analyze(chart: chart, flowYear: year),
      ..._timing(keys, chart),
    ];
    final functions = Map<String, String>.from(elementFunction);

    final text = formatReport(
      chart: chart,
      keys: keys,
      resonance: resonance,
      energy: energy,
      liuQin: liuQin,
      structureType: structure,
      coreKeys: core,
      digestion: digestion,
      timingHints: timing,
      functionTranslation: functions,
    );

    return JudgmentReport(
      chart: chart,
      keys: keys,
      resonance: resonance,
      energy: energy,
      liuQin: liuQin,
      structureType: structure,
      coreKeys: core,
      digestion: digestion,
      timingHints: timing,
      functionTranslation: functions,
      rawText: text,
      accuracyCap: maxAccuracy,
    );
  }

  static String _structureType(BaziChart chart, EnergyProfile energy) {
    final dm = GanZhi.stemElement[chart.dayMaster]!;
    final dmE = energy.elementEnergy[dm] ?? 0;
    final total =
        energy.elementEnergy.values.fold<double>(0, (a, b) => a + b);
    if (total > 0 && dmE / total < 0.12) return '从格倾向（日主偏弱，需验）';
    if (total > 0 && dmE / total > 0.35) return '正格·身旺倾向';
    return '正格';
  }

  static String _digestion(List<KeyRelation> keys) {
    final hasClash = keys.any((k) => k.type.contains('冲'));
    final hasHe = keys.any((k) => k.type.contains('合'));
    final count = keys.length;
    if (hasClash && !hasHe) return '破坏（损伤）';
    if (hasHe && count >= 8) return '缓冲（分流）';
    if (hasHe) return '同化（吸收）';
    if (count < 3) return '抵御（隔绝）';
    return '缓冲（分流）';
  }

  static List<String> _timing(List<KeyRelation> keys, BaziChart chart) {
    final hints = <String>[];
    for (final k in keys.where((k) =>
        k.type.contains('冲') ||
        k.type.contains('合') ||
        k.type.contains('刑'))) {
      hints.add('成局：${k.detail} — 逢透干+外应则必应');
    }
    for (final dy in chart.daYun.take(2)) {
      hints.add('大运${dy.text}期间相关键易显化');
    }
    if (hints.isEmpty) {
      hints.add('静观流年与大运成键后再断应期');
    }
    return hints.take(10).toList();
  }

  static String formatReport({
    required BaziChart chart,
    required List<KeyRelation> keys,
    required ResonanceResult resonance,
    required EnergyProfile energy,
    required List<LiuQinEntry> liuQin,
    required String structureType,
    required List<String> coreKeys,
    required String digestion,
    required List<String> timingHints,
    required Map<String, String> functionTranslation,
  }) {
    final input = chart.input;
    final c = chart.correction;
    final dm = chart.dayMaster;
    final buf = StringBuffer();

    buf.writeln('=== 键共振命理判局报告 ===');
    buf.writeln();
    buf.writeln('一、基本信息');
    buf.writeln('- 姓名：${input.name}');
    buf.writeln('- 出生时间：${input.localDateTime}');
    buf.writeln('- 出生地点：${input.placeName}');
    buf.writeln('- 经纬度：${input.longitude} / ${input.latitude}');
    buf.writeln('- 性别：${input.gender == Gender.male ? "男" : "女"}');
    buf.writeln();
    buf.writeln('二、时空校正');
    buf.writeln('- 换算北京时：${c.beijingTime}');
    buf.writeln('- 日柱偏移：${c.dayPillarOffset}');
    buf.writeln('- 是否南半球：${c.southernHemisphere ? "是" : "否"}');
    buf.writeln('- 跨大西洋日界：${c.crossedDateLine ? "是" : "否"}');
    buf.writeln();
    buf.writeln('三、排盘结果');
    buf.writeln('- 四柱八字：${chart.fourPillarsText}');
    buf.writeln(
        '- 日主：$dm ${GanZhi.stemYinYang[dm]} ${GanZhi.stemElement[dm]}');
    buf.writeln(
        '- 大运：${chart.daYun.map((p) => p.text).join(" → ")}');
    buf.writeln(
        '- 小运：${chart.xiaoYun.take(5).map((p) => p.text).join(" → ")}…');
    buf.writeln();
    buf.writeln('四、键网络识别');
    void section(String title, String type) {
      final items = keys.where((k) => k.type == type).map((k) => k.detail);
      buf.writeln('- $title：${items.isEmpty ? "无" : items.join("；")}');
    }

    section('天干五合', '天干五合');
    section('地支六合', '地支六合');
    section('地支三合', '地支三合');
    section('地支三会', '地支三会');
    section('地支六冲', '地支六冲');
    section('地支三刑', '地支三刑');
    section('地支六害', '地支六害');
    section('地支六破', '地支六破');
    section('同字共振', '同字共振');
    section('同行共振', '同行共振');
    buf.writeln();
    buf.writeln('五、共振与纠缠判断');
    for (final r in resonance.resonanceKeys.take(12)) {
      buf.writeln(
          '- 共振键：${r.detail} → 能量倍数：×${r.baseMultiplier.clamp(1, 6)}');
    }
    for (final e in resonance.entanglementKeys.take(8)) {
      buf.writeln('- 纠缠键：${e.detail}');
    }
    buf.writeln();
    buf.writeln('六、能量分析');
    buf.writeln(
        '- 五行能量分布：${energy.elementEnergy.entries.map((e) => "${e.key}${e.value.toStringAsFixed(2)}").join(" ")}');
    buf.writeln('- 当令/不当令：当令${energy.seasonalElement}');
    buf.writeln(
        '- 通根情况：${energy.roots.isEmpty ? "无" : energy.roots.join("；")}');
    buf.writeln(
        '- 开库情况：${energy.openVaults.isEmpty ? "无" : energy.openVaults.join("、")} → 余气释放：0.1→0.5');
    buf.writeln();
    buf.writeln('七、六亲定位');
    for (final q in liuQin.where((q) => q.layer.contains('第一'))) {
      buf.writeln(
          '- ${q.relation}：${q.stem}（${q.tenGod}） [${q.source}]${q.palace != null ? " 宫位:${q.palace}" : ""}');
    }
    buf.writeln('- 大运小运显化（家内）：');
    for (final q in liuQin.where((q) => q.layer.contains('第二')).take(6)) {
      buf.writeln('  · ${q.relation} ${q.stem} @ ${q.source}');
    }
    buf.writeln('- 流年十神身份（家外）：');
    for (final q in liuQin.where((q) => q.layer.contains('第三'))) {
      buf.writeln('  · ${q.relation} ${q.stem} ${q.tenGod}');
    }
    buf.writeln();
    buf.writeln('八、结构判断');
    buf.writeln('- 结构类型：$structureType');
    buf.writeln(
        '- 核心键：${coreKeys.isEmpty ? "见键网络" : coreKeys.join("；")}');
    buf.writeln('- 消化机制：$digestion');
    buf.writeln();
    buf.writeln('九、应期判断');
    for (final t in timingHints) {
      buf.writeln('- $t');
    }
    buf.writeln('- 判断依据：成局+透干+外应');
    buf.writeln();
    buf.writeln('十、功能翻译');
    for (final e in functionTranslation.entries) {
      buf.writeln('- ${e.key}：${e.value}');
    }
    buf.writeln();
    buf.writeln('十一、边界提示');
    buf.writeln('- 最高准确率：80%（531理论：命50%+运30%）');
    buf.writeln('- 剩余空间：地理10% + 意识5% + 天意5%');
    buf.writeln();
    buf.writeln('十二、版权信息');
    buf.writeln('- $copyright');
    buf.writeln('- $appName · Developer: $developerName');

    return buf.toString();
  }

  /// 531 理论边界提示
  static String theory531Hint() =>
      '531理论边界：命50% + 运30% + 地理10% + 意识5% + 天意5% = 最高准确率80%。';
}
