from django.test import TestCase, Client
from django.contrib.auth import get_user_model
from django.core.cache import cache
from unittest.mock import patch
from datetime import date, datetime, timedelta

from bazi.models import Person
from iching.utils import bzshagod as sg
from iching.utils import bz as bzu
from iching.utils.person_good_days import evaluate_good_day

User = get_user_model()


def reverse_shagod_index(name: str) -> int:
    return {v: k for k, v in sg.gShagodFnNames.items()}[name]


class BaziGoodDaysRuleTests(TestCase):
    RELATION_DATA = """
[liuhe]
1905-01-06 08:00:00 (day.g=乙, day.e=巳), 1915-01-05 11:00:00 (day.g=丙, day.e=申)
1912-01-01 08:00:00 (day.g=丙, day.e=子), 1924-01-11 11:00:00 (day.g=己, day.e=丑)
1928-01-04 08:00:00 (day.g=癸, day.e=卯), 1943-01-04 11:00:00 (day.g=壬, day.e=戌)
1937-01-05 08:00:00 (day.g=壬, day.e=辰), 1955-01-12 11:00:00 (day.g=癸, day.e=酉)
1944-01-07 08:00:00 (day.g=庚, day.e=午), 1964-01-11 11:00:00 (day.g=己, day.e=未)
1956-01-12 08:00:00 (day.g=戊, day.e=寅), 1981-01-09 11:00:00 (day.g=丁, day.e=亥)
1967-01-05 08:00:00 (day.g=己, day.e=巳), 1997-01-06 11:00:00 (day.g=戊, day.e=申)
1977-01-07 08:00:00 (day.g=甲, day.e=子), 1991-01-07 11:00:00 (day.g=丁, day.e=丑)
1988-01-01 08:00:00 (day.g=乙, day.e=卯), 2010-01-12 11:00:00 (day.g=壬, day.e=戌)
1998-01-09 08:00:00 (day.g=丙, day.e=辰), 2026-01-11 11:00:00 (day.g=乙, day.e=酉)

[sanhe]
1937-01-09 08:00:00 (day.g=丙, day.e=申), 1962-04-08 11:00:00 (day.g=丙, day.e=子, month.e=辰)
1944-01-12 08:00:00 (day.g=乙, day.e=亥), 1974-07-13 11:00:00 (day.g=乙, day.e=卯, month.e=未)
1956-01-12 08:00:00 (day.g=戊, day.e=寅), 1970-10-17 11:00:00 (day.g=庚, day.e=午, month.e=戌)
1967-01-05 08:00:00 (day.g=己, day.e=巳), 1989-01-13 11:00:00 (day.g=癸, day.e=酉, month.e=丑)
1977-01-03 08:00:00 (day.g=庚, day.e=申), 2005-04-10 11:00:00 (day.g=甲, day.e=子, month.e=辰)
1988-01-09 08:00:00 (day.g=癸, day.e=亥), 1997-07-12 11:00:00 (day.g=乙, day.e=卯, month.e=未)
1998-01-07 08:00:00 (day.g=甲, day.e=寅), 2014-10-14 11:00:00 (day.g=戊, day.e=午, month.e=戌)
2001-01-06 08:00:00 (day.g=己, day.e=巳), 2022-01-08 11:00:00 (day.g=辛, day.e=酉, month.e=丑)
2005-01-12 08:00:00 (day.g=丙, day.e=申), 2029-04-04 11:00:00 (day.g=甲, day.e=子, month.e=辰)
2010-01-01 08:00:00 (day.g=辛, day.e=亥), 2021-07-18 11:00:00 (day.g=丁, day.e=卯, month.e=未)

[tian_yi]
1912-01-09 08:00:00 (day.g=甲, day.e=申), 1926-01-06 08:00:00 (day.g=乙, day.e=未)
1928-01-06 08:00:00 (day.g=乙, day.e=巳), 1950-01-01 08:00:00 (day.g=丙, day.e=申)
1937-01-09 08:00:00 (day.g=丙, day.e=申), 1965-01-07 08:00:00 (day.g=辛, day.e=酉)
1944-01-04 08:00:00 (day.g=丁, day.e=卯), 1953-01-12 08:00:00 (day.g=癸, day.e=亥)
1956-01-02 08:00:00 (day.g=戊, day.e=辰), 1972-01-11 08:00:00 (day.g=辛, day.e=丑)
1967-01-05 08:00:00 (day.g=己, day.e=巳), 1988-01-10 08:00:00 (day.g=甲, day.e=子)
1977-01-03 08:00:00 (day.g=庚, day.e=申), 2001-01-02 08:00:00 (day.g=乙, day.e=丑)
1988-01-07 08:00:00 (day.g=辛, day.e=酉), 1999-01-02 08:00:00 (day.g=甲, day.e=寅)
1998-01-05 08:00:00 (day.g=壬, day.e=子), 2008-01-04 08:00:00 (day.g=癸, day.e=卯)
2001-01-10 08:00:00 (day.g=癸, day.e=酉), 2013-01-03 08:00:00 (day.g=己, day.e=巳)
1998-01-07 08:00:00 (day.g=甲, day.e=寅), 2016-01-08 08:00:00 (day.g=己, day.e=丑)
2001-01-02 08:00:00 (day.g=乙, day.e=丑), 2021-01-04 08:00:00 (day.g=壬, day.e=子)
2005-01-02 08:00:00 (day.g=丙, day.e=戌), 2030-01-04 08:00:00 (day.g=己, day.e=亥)
2010-01-07 08:00:00 (day.g=丁, day.e=巳), 2040-01-10 08:00:00 (day.g=丁, day.e=酉)
2015-01-02 08:00:00 (day.g=戊, day.e=寅), 2029-01-05 08:00:00 (day.g=乙, day.e=未)
2019-01-02 08:00:00 (day.g=己, day.e=亥), 2041-01-03 08:00:00 (day.g=丙, day.e=申)
1905-01-01 08:00:00 (day.g=庚, day.e=子), 1933-01-05 08:00:00 (day.g=辛, day.e=未)
1912-01-06 08:00:00 (day.g=辛, day.e=巳), 1921-01-07 08:00:00 (day.g=庚, day.e=午)
1928-01-03 08:00:00 (day.g=壬, day.e=寅), 1944-01-06 08:00:00 (day.g=己, day.e=巳)
1937-01-06 08:00:00 (day.g=癸, day.e=巳), 1958-01-02 08:00:00 (day.g=己, day.e=卯)

[wenchang]
1956-01-08 08:00:00 (day.g=甲, day.e=戌), 1984-01-12 08:00:00 (day.g=乙, day.e=巳)
1967-01-01 08:00:00 (day.g=乙, day.e=丑), 1976-01-07 08:00:00 (day.g=戊, day.e=午)
1977-01-09 08:00:00 (day.g=丙, day.e=寅), 1993-01-03 08:00:00 (day.g=甲, day.e=申)
1988-01-03 08:00:00 (day.g=丁, day.e=巳), 2009-01-04 08:00:00 (day.g=己, day.e=酉)
1998-01-01 08:00:00 (day.g=戊, day.e=申), 2022-01-07 08:00:00 (day.g=庚, day.e=申)
2001-01-06 08:00:00 (day.g=己, day.e=巳), 2012-01-01 08:00:00 (day.g=辛, day.e=酉)
2005-01-06 08:00:00 (day.g=庚, day.e=寅), 2015-01-11 08:00:00 (day.g=丁, day.e=亥)
2010-01-01 08:00:00 (day.g=辛, day.e=亥), 2022-01-11 08:00:00 (day.g=甲, day.e=子)
2015-01-06 08:00:00 (day.g=壬, day.e=午), 2030-01-07 08:00:00 (day.g=壬, day.e=寅)
2019-01-06 08:00:00 (day.g=癸, day.e=卯), 2037-01-07 08:00:00 (day.g=己, day.e=卯)

[taohua]
1928-01-01 08:00:00 (day.g=庚, day.e=子), 1948-01-01 08:00:00 (day.g=乙, day.e=酉)
1937-01-02 08:00:00 (day.g=己, day.e=丑), 1962-01-08 08:00:00 (day.g=丙, day.e=午)
1944-01-03 08:00:00 (day.g=丙, day.e=寅), 1974-01-02 08:00:00 (day.g=癸, day.e=卯)
1956-01-01 08:00:00 (day.g=丁, day.e=卯), 1970-01-08 08:00:00 (day.g=戊, day.e=子)
1967-01-04 08:00:00 (day.g=戊, day.e=辰), 1989-01-01 08:00:00 (day.g=辛, day.e=酉)
1977-01-12 08:00:00 (day.g=己, day.e=巳), 2005-01-10 08:00:00 (day.g=甲, day.e=午)
1988-01-04 08:00:00 (day.g=戊, day.e=午), 1997-01-01 08:00:00 (day.g=癸, day.e=卯)
1998-01-12 08:00:00 (day.g=己, day.e=未), 2014-01-05 08:00:00 (day.g=丙, day.e=子)
2001-01-09 08:00:00 (day.g=壬, day.e=申), 2022-01-08 08:00:00 (day.g=辛, day.e=酉)
2005-01-01 08:00:00 (day.g=乙, day.e=酉), 2029-01-04 08:00:00 (day.g=甲, day.e=午)

[liuchong]
1905-01-01 08:00:00 (day.g=庚, day.e=子), 1915-01-01 08:00:00 (day.g=乙, day.e=午)
1912-01-01 08:00:00 (day.g=丙, day.e=子), 1924-01-01 08:00:00 (day.g=己, day.e=午)
1928-01-01 08:00:00 (day.g=癸, day.e=子), 1943-01-01 08:00:00 (day.g=壬, day.e=午)
1937-01-01 08:00:00 (day.g=壬, day.e=子), 1955-01-01 08:00:00 (day.g=癸, day.e=午)
1944-01-01 08:00:00 (day.g=庚, day.e=子), 1964-01-01 08:00:00 (day.g=己, day.e=午)
1956-01-01 08:00:00 (day.g=戊, day.e=子), 1981-01-01 08:00:00 (day.g=丁, day.e=午)
1967-01-01 08:00:00 (day.g=己, day.e=子), 1997-01-01 08:00:00 (day.g=戊, day.e=午)
1977-01-01 08:00:00 (day.g=甲, day.e=子), 1991-01-01 08:00:00 (day.g=丁, day.e=午)
1988-01-01 08:00:00 (day.g=乙, day.e=子), 2010-01-01 08:00:00 (day.g=壬, day.e=午)
1998-01-01 08:00:00 (day.g=丙, day.e=子), 2026-01-01 08:00:00 (day.g=乙, day.e=午)

[edge_cases]
liuhe-no:  1988-01-10 08:00:00 (day.g=甲, day.e=子), 1990-01-11 22:59:59 (day.g=丙, day.e=子)
liuhe-yes: 1988-01-10 08:00:00 (day.g=甲, day.e=子), 1990-01-11 23:00:00 (day.g=丁, day.e=丑)
sanhe-no:  1967-01-08 08:00:00 (day.g=壬, day.e=申), 1991-04-11 22:59:59 (day.g=辛, day.e=亥, month.g=壬, month.e=辰)
sanhe-yes: 1967-01-08 08:00:00 (day.g=壬, day.e=申), 1991-04-11 23:00:00 (day.g=壬, day.e=子, month.g=壬, month.e=辰)
tian_yi-no:  1988-01-10 08:00:00 (day.g=甲, day.e=子), 1992-01-07 22:59:59 (day.g=壬, day.e=午)
tian_yi-yes: 1988-01-10 08:00:00 (day.g=甲, day.e=子), 1992-01-07 23:00:00 (day.g=癸, day.e=未)
wenchang-no:  1988-01-10 08:00:00 (day.g=甲, day.e=子), 1993-01-11 22:59:59 (day.g=壬, day.e=辰)
wenchang-yes: 1988-01-10 08:00:00 (day.g=甲, day.e=子), 1993-01-11 23:00:00 (day.g=癸, day.e=巳)
taohua-no:  1988-01-10 08:00:00 (day.g=甲, day.e=子), 1994-01-10 22:59:59 (day.g=丙, day.e=申)
taohua-yes: 1988-01-10 08:00:00 (day.g=甲, day.e=子), 1994-01-10 23:00:00 (day.g=丁, day.e=酉)

[liuhe_not]
1905-01-01 08:00:00 (day.g=庚, day.e=子), 1915-01-11 08:00:00 (day.g=壬, day.e=寅)
1912-01-01 08:00:00 (day.g=丙, day.e=子), 1924-01-05 08:00:00 (day.g=癸, day.e=未)
1928-01-02 08:00:00 (day.g=辛, day.e=丑), 1943-01-08 08:00:00 (day.g=丙, day.e=寅)
1937-01-02 08:00:00 (day.g=己, day.e=丑), 1955-01-10 08:00:00 (day.g=辛, day.e=未)
1944-01-03 08:00:00 (day.g=丙, day.e=寅), 1964-01-04 08:00:00 (day.g=壬, day.e=子)
1956-01-12 08:00:00 (day.g=戊, day.e=寅), 1981-01-04 08:00:00 (day.g=壬, day.e=午)
1967-01-03 08:00:00 (day.g=丁, day.e=卯), 1997-01-10 08:00:00 (day.g=壬, day.e=子)
1977-01-10 08:00:00 (day.g=丁, day.e=卯), 2009-01-01 08:00:00 (day.g=丙, day.e=午)
1988-01-02 08:00:00 (day.g=丙, day.e=辰), 2023-01-06 08:00:00 (day.g=甲, day.e=子)
1998-01-09 08:00:00 (day.g=丙, day.e=辰), 2038-01-05 08:00:00 (day.g=壬, day.e=午)

[sanhe_not]
1912-01-09 08:00:00 (day.g=甲, day.e=申), 1927-01-09 08:00:00 (day.g=癸, day.e=卯)
1928-01-01 08:00:00 (day.g=庚, day.e=子), 1946-01-05 08:00:00 (day.g=己, day.e=卯)
1937-01-05 08:00:00 (day.g=壬, day.e=辰), 1957-01-07 08:00:00 (day.g=己, day.e=卯)
1944-01-04 08:00:00 (day.g=丁, day.e=卯), 1969-01-03 08:00:00 (day.g=戊, day.e=寅)
1956-01-09 08:00:00 (day.g=乙, day.e=亥), 1986-01-10 08:00:00 (day.g=甲, day.e=寅)
1967-01-07 08:00:00 (day.g=辛, day.e=未), 1999-01-02 08:00:00 (day.g=甲, day.e=寅)
1977-01-09 08:00:00 (day.g=丙, day.e=寅), 2012-01-01 08:00:00 (day.g=辛, day.e=酉)
1988-01-08 08:00:00 (day.g=壬, day.e=戌), 2028-01-01 08:00:00 (day.g=乙, day.e=酉)
1998-01-11 08:00:00 (day.g=戊, day.e=午), 2008-01-10 08:00:00 (day.g=己, day.e=酉)
2001-01-10 08:00:00 (day.g=癸, day.e=酉), 2013-01-06 08:00:00 (day.g=壬, day.e=申)

[tian_yi_not]
1928-01-05 08:00:00 (day.g=甲, day.e=辰), 1958-01-11 08:00:00 (day.g=戊, day.e=子)
1937-01-08 08:00:00 (day.g=乙, day.e=未), 1969-01-02 08:00:00 (day.g=丁, day.e=丑)
1944-01-03 08:00:00 (day.g=丙, day.e=寅), 1979-01-09 08:00:00 (day.g=丙, day.e=子)
1956-01-01 08:00:00 (day.g=丁, day.e=卯), 1996-01-04 08:00:00 (day.g=庚, day.e=子)
1967-01-04 08:00:00 (day.g=戊, day.e=辰), 1977-01-07 08:00:00 (day.g=甲, day.e=子)
1977-01-02 08:00:00 (day.g=己, day.e=未), 1989-01-05 08:00:00 (day.g=乙, day.e=丑)
1988-01-06 08:00:00 (day.g=庚, day.e=申), 2003-01-03 08:00:00 (day.g=丙, day.e=子)
1998-01-04 08:00:00 (day.g=辛, day.e=亥), 2016-01-07 08:00:00 (day.g=戊, day.e=子)
2001-01-09 08:00:00 (day.g=壬, day.e=申), 2021-01-04 08:00:00 (day.g=壬, day.e=子)
2005-01-09 08:00:00 (day.g=癸, day.e=巳), 2030-01-05 08:00:00 (day.g=庚, day.e=子)

[wenchang_not]
1944-01-01 08:00:00 (day.g=甲, day.e=子), 1979-01-09 08:00:00 (day.g=丙, day.e=子)
1956-01-09 08:00:00 (day.g=乙, day.e=亥), 1996-01-04 08:00:00 (day.g=庚, day.e=子)
1967-01-02 08:00:00 (day.g=丙, day.e=寅), 1977-01-07 08:00:00 (day.g=甲, day.e=子)
1977-01-10 08:00:00 (day.g=丁, day.e=卯), 1989-01-04 08:00:00 (day.g=甲, day.e=子)
1988-01-04 08:00:00 (day.g=戊, day.e=午), 2003-01-03 08:00:00 (day.g=丙, day.e=子)
1998-01-02 08:00:00 (day.g=己, day.e=酉), 2016-01-07 08:00:00 (day.g=戊, day.e=子)
2001-01-07 08:00:00 (day.g=庚, day.e=午), 2021-01-04 08:00:00 (day.g=壬, day.e=子)
2005-01-07 08:00:00 (day.g=辛, day.e=卯), 2030-01-06 08:00:00 (day.g=辛, day.e=丑)
2010-01-02 08:00:00 (day.g=壬, day.e=子), 2040-01-01 08:00:00 (day.g=戊, day.e=子)
2015-01-07 08:00:00 (day.g=癸, day.e=未), 2047-01-12 08:00:00 (day.g=丙, day.e=子)

[taohua_not]
1937-01-01 08:00:00 (day.g=戊, day.e=子), 1969-01-01 08:00:00 (day.g=丙, day.e=子)
1944-01-02 08:00:00 (day.g=乙, day.e=丑), 1979-01-09 08:00:00 (day.g=丙, day.e=子)
1956-01-12 08:00:00 (day.g=戊, day.e=寅), 1996-01-04 08:00:00 (day.g=庚, day.e=子)
1967-01-03 08:00:00 (day.g=丁, day.e=卯), 1977-01-08 08:00:00 (day.g=乙, day.e=丑)
1977-01-11 08:00:00 (day.g=戊, day.e=辰), 1989-01-04 08:00:00 (day.g=甲, day.e=子)
1988-01-03 08:00:00 (day.g=丁, day.e=巳), 2003-01-03 08:00:00 (day.g=丙, day.e=子)
1998-01-11 08:00:00 (day.g=戊, day.e=午), 2016-01-07 08:00:00 (day.g=戊, day.e=子)
2001-01-08 08:00:00 (day.g=辛, day.e=未), 2021-01-05 08:00:00 (day.g=癸, day.e=丑)
2005-01-12 08:00:00 (day.g=丙, day.e=申), 2030-01-05 08:00:00 (day.g=庚, day.e=子)
2010-01-11 08:00:00 (day.g=辛, day.e=酉), 2040-01-01 08:00:00 (day.g=戊, day.e=子)
"""

    @staticmethod
    def _parse_pairs(section: str):
        lines = [l.strip() for l in section.splitlines() if l.strip() and not l.strip().startswith('[')]
        pairs = []
        for line in lines:
            # Split by comma between two datetime entries
            left, right = line.split('),')
            left_dt = left.split('(')[0].strip()
            right_dt = right.strip().split('(')[0].strip()
            dt1 = datetime.strptime(left_dt, '%Y-%m-%d %H:%M:%S')
            dt2 = datetime.strptime(right_dt, '%Y-%m-%d %H:%M:%S')
            pairs.append((dt1, dt2))
        return pairs

    @classmethod
    def _get_section(cls, name: str) -> str:
        blob = cls.RELATION_DATA
        parts = blob.split(f'[{name}]')
        if len(parts) < 2:
            return ''
        tail = parts[1]
        # cut at next section if any
        for marker in ['[liuhe]', '[sanhe]', '[tian_yi]', '[wenchang]', '[taohua]', '[liuchong]', '[edge_cases]']:
            if marker == f'[{name}]':
                continue
            if marker in tail:
                tail = tail.split(marker)[0]
        return tail
    def setUp(self):
        self.user = User.objects.create_user(
            phone='5566778899', email='rules@example.com', password='pw123456'
        )
        self.client = Client()
        self.client.login(phone='5566778899', password='pw123456')

        self.person = Person.objects.create(
            name='Owner',
            gender='N',
            birth_date=date(1990, 1, 1),
            owner=True,
            created_by=self.user,
        )
        # User day pillar: 甲子 => g=0 (甲), e=0 (子)
        self.person.bazi_result = {
            'year': {'god': 0, 'earth': 0},
            'month': {'god': 0, 'earth': 0},
            'day': {'god': 0, 'earth': 0},
        }
        self.person.save()

        self.url = '/api/bazi/good-days/'

        # Bump cache version to isolate between tests
        ver = cache.get('bz_good_days_version', 1)
        cache.set('bz_good_days_version', ver + 1, None)

    def _mock_bazi(self, day_g: int, day_e: int, month_e: int):
        return {
            'year': {'g': 0, 'e': 0},
            'month': {'g': 0, 'e': month_e},
            'day': {'g': day_g, 'e': day_e},
            'hour': {'g': 0, 'e': 0},
        }

    def test_liuhe(self):
        section = self._get_section('liuhe')
        pairs = self._parse_pairs(section)[:2]
        for dt1, dt2 in pairs:
            b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
            b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
            reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
            self.assertTrue(any(r.get('t') == 'r' and r.get('c') == 'liuhe' for r in reasons))

    def test_liuchong(self):
        # Test with a simple case: user with day branch 0 (子) and target date with day branch 6 (午)
        # This should create a 六冲 relationship
        user_day_g = 0  # 甲
        user_day_e = 0  # 子
        target_bazi = {
            'year': {'g': 0, 'e': 0},
            'month': {'g': 0, 'e': 0},
            'day': {'g': 0, 'e': 6},  # 午 - should clash with 子
            'hour': {'g': 0, 'e': 0},
        }
        reasons = evaluate_good_day(user_day_g, user_day_e, target_bazi)
        self.assertTrue(any(r.get('t') == 'r' and r.get('c') == 'liuchong' for r in reasons))

    def test_bansanhe(self):
        # Use sanhe pair but break month to avoid full 三合
        section = self._get_section('sanhe')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        # Break the month.e deliberately
        b2_mod = dict(b2)
        b2_mod['month'] = dict(b2['month'])
        b2_mod['month']['e'] = (b2['month']['e'] + 1) % 12
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2_mod)
        self.assertTrue(any(r.get('t') == 'r' and r.get('c') == 'bansanhe' for r in reasons))
        self.assertFalse(any(r.get('t') == 'r' and r.get('c') == 'sanhe' for r in reasons))

    def test_sanhe(self):
        section = self._get_section('sanhe')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
        self.assertTrue(any(r.get('t') == 'r' and r.get('c') == 'sanhe' for r in reasons))

    def test_tian_yi(self):
        section = self._get_section('tian_yi')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
        idx = reverse_shagod_index('tian_yi')
        self.assertTrue(any(r.get('t') == 's' and r.get('i') == idx for r in reasons))

    def test_wenchang(self):
        section = self._get_section('wenchang')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
        idx = reverse_shagod_index('wenchang')
        self.assertTrue(any(r.get('t') == 's' and r.get('i') == idx for r in reasons))

    def test_taohua(self):
        section = self._get_section('taohua')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
        idx = reverse_shagod_index('taohua')
        self.assertTrue(any(r.get('t') == 's' and r.get('i') == idx for r in reasons))

    def test_liuhe_not(self):
        section = self._get_section('liuhe_not')
        if not section:
            self.skipTest('liuhe_not data not present')
        pairs = self._parse_pairs(section)[:3]
        for dt1, dt2 in pairs:
            b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
            b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
            reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
            self.assertFalse(any(r.get('t') == 'r' and r.get('c') == 'liuhe' for r in reasons))

    def test_sanhe_not(self):
        section = self._get_section('sanhe_not')
        if not section:
            self.skipTest('sanhe_not data not present')
        pairs = self._parse_pairs(section)[:3]
        for dt1, dt2 in pairs:
            b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
            b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
            reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
            self.assertFalse(any(r.get('t') == 'r' and r.get('c') in ('sanhe', 'bansanhe') for r in reasons))

    def test_tian_yi_not(self):
        section = self._get_section('tian_yi_not')
        if not section:
            self.skipTest('tian_yi_not data not present')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
        idx = reverse_shagod_index('tian_yi')
        self.assertFalse(any(r.get('t') == 's' and r.get('i') == idx for r in reasons))

    def test_wenchang_not(self):
        section = self._get_section('wenchang_not')
        if not section:
            self.skipTest('wenchang_not data not present')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
        idx = reverse_shagod_index('wenchang')
        self.assertFalse(any(r.get('t') == 's' and r.get('i') == idx for r in reasons))

    def test_taohua_not(self):
        section = self._get_section('taohua_not')
        if not section:
            self.skipTest('taohua_not data not present')
        dt1, dt2 = self._parse_pairs(section)[0]
        b1 = bzu.getCalendar10kGodEarthStem(dt1.year, dt1.month, dt1.day, dt1.hour, dt1.minute, dt1.second)
        b2 = bzu.getCalendar10kGodEarthStem(dt2.year, dt2.month, dt2.day, 22, 59, 59)
        reasons = evaluate_good_day(b1['day']['g'], b1['day']['e'], b2)
        idx = reverse_shagod_index('taohua')
        self.assertFalse(any(r.get('t') == 's' and r.get('i') == idx for r in reasons))

