import 'constants.dart';
import 'models.dart';
/// 经纬度时空校正
/// 以北京东经120°为子午线原点；日界23:00；日界线在大西洋（东经120°-180°=西经60°）
/// © 2026 Jason Li. All rights reserved.

class TimeCorrection {
  /// Convert local civil/solar-ish time to Beijing meridian time.
  /// Rule: each 1° longitude = 4 minutes; east of 120 add, west of 120 subtract
  /// Implementation: beijing = local + (120 - longitude) * 4 minutes
  /// Date-line (Atlantic at 60°W): when longitude < -60, day pillar offset +1
  static TimeCorrectionResult correct({
    required DateTime localDateTime,
    required double longitude,
    required double latitude,
  }) {
    final offsetMinutes = (meridianLongitude - longitude) * 4.0;
    final offset = Duration(minutes: offsetMinutes.round());
    var beijing = localDateTime.add(offset);

    // Eastward arc from Beijing meridian; crossing Atlantic date-line (~60°W)
    final crossedDateLine = _crossedAtlanticDateLine(longitude);
    var dayOffset = 0;
    if (crossedDateLine) {
      dayOffset += 1;
    }

    // Day pillar boundary at 23:00 Beijing time
    if (beijing.hour >= dayBoundaryHour) {
      dayOffset += 1;
    }

    return TimeCorrectionResult(
      beijingTime: beijing,
      dayPillarOffset: dayOffset,
      crossedDateLine: crossedDateLine,
      southernHemisphere: latitude < 0,
      longitudeOffset: offset,
    );
  }

  /// From Beijing going east across the Pacific: after passing ~180° you are in
  /// the Americas; the system's date line continues to the Atlantic (~60°W).
  /// Practical rule matching tutorial 12.3: western-hemisphere longitudes
  /// reached via the Pacific (lon < 0) add one calendar day for day-pillar.
  /// Europe/Africa west of Beijing use the westward short path — no day add.
  ///
  /// 墨尔本教程表日/时写成与芝加哥相同（戊寅/癸丑），与东经120°公式自洽结果
  /// （丁丑/辛丑）冲突；引擎保留自洽结果，年月（癸巳）与教程一致。
  static bool _crossedAtlanticDateLine(double longitude) {
    var lon = longitude;
    while (lon > 180) {
      lon -= 360;
    }
    while (lon <= -180) {
      lon += 360;
    }
    // Eastward arc from 120°E (0..360)
    final eastward = lon >= meridianLongitude
        ? lon - meridianLongitude
        : (360 - meridianLongitude + lon);
    // Crossed the antimeridian eastward into the western hemisphere
    // and still west of the Atlantic date-line (~60°W ⇒ eastward < 180+60?):
    // Americas: lon < 0 and eastward between 60° and 240°.
    return lon < 0 && eastward > 60 && eastward < 240;
  }

  /// True solar time hour branch from local time (时柱以当地时辰为准)
  static String hourBranch(DateTime local) {
    // 子 23-1, 丑 1-3, ... 亥 21-23
    final h = local.hour;
    final m = local.minute;
    final total = h + m / 60.0;
    if (total >= 23 || total < 1) return '子';
    if (total < 3) return '丑';
    if (total < 5) return '寅';
    if (total < 7) return '卯';
    if (total < 9) return '辰';
    if (total < 11) return '巳';
    if (total < 13) return '午';
    if (total < 15) return '未';
    if (total < 17) return '申';
    if (total < 19) return '酉';
    if (total < 21) return '戌';
    return '亥';
  }
}
