"""
Part 5 AI 핵심 라이브러리 테스트 코드
"""

import os
import sys
import unittest

import numpy as np
import pandas as pd

# 상위 디렉토리의 모듈을 import하기 위한 경로 추가
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))


class TestAICoreLibraries(unittest.TestCase):
    """AI 핵심 라이브러리 테스트 클래스"""

    def setUp(self):
        """테스트 설정"""
        self.sample_data = np.array([1, 2, 3, 4, 5])
        self.sample_df = pd.DataFrame({"A": [1, 2, 3, 4, 5], "B": [10, 20, 30, 40, 50]})

    def test_numpy_operations(self):
        """NumPy 연산 테스트"""
        # 기본 연산 테스트
        result = np.mean(self.sample_data)
        self.assertEqual(result, 3.0)

        # 배열 생성 테스트
        zeros_array = np.zeros(5)
        self.assertEqual(len(zeros_array), 5)
        self.assertTrue(np.all(zeros_array == 0))

        # 행렬 연산 테스트
        matrix_a = np.array([[1, 2], [3, 4]])
        matrix_b = np.array([[5, 6], [7, 8]])
        result = np.dot(matrix_a, matrix_b)
        expected = np.array([[19, 22], [43, 50]])
        np.testing.assert_array_equal(result, expected)

    def test_pandas_operations(self):
        """Pandas 연산 테스트"""
        # 기본 통계 테스트
        mean_a = self.sample_df["A"].mean()
        self.assertEqual(mean_a, 3.0)

        # 데이터 필터링 테스트
        filtered = self.sample_df[self.sample_df["A"] > 3]
        self.assertEqual(len(filtered), 2)

        # 새 열 추가 테스트
        self.sample_df["C"] = self.sample_df["A"] + self.sample_df["B"]
        self.assertTrue("C" in self.sample_df.columns)
        self.assertEqual(self.sample_df["C"].iloc[0], 11)

    def test_matplotlib_basic(self):
        """Matplotlib 기본 기능 테스트"""
        try:
            import matplotlib.pyplot as plt

            # 기본 플롯 생성 테스트
            fig, ax = plt.subplots()
            ax.plot([1, 2, 3, 4], [1, 4, 2, 3])

            # 플롯 객체가 올바르게 생성되었는지 확인
            self.assertIsNotNone(fig)
            self.assertIsNotNone(ax)

            plt.close(fig)  # 메모리 해제

        except ImportError:
            self.skipTest("Matplotlib가 설치되지 않았습니다.")

    def test_data_preprocessing(self):
        """데이터 전처리 기능 테스트"""
        # 결측값 처리 테스트
        data_with_nan = pd.DataFrame(
            {"A": [1, 2, np.nan, 4, 5], "B": [10, np.nan, 30, 40, 50]}
        )

        # 결측값 제거
        cleaned_data = data_with_nan.dropna()
        self.assertEqual(len(cleaned_data), 3)

        # 결측값 채우기
        filled_data = data_with_nan.fillna(0)
        self.assertFalse(filled_data.isnull().any().any())

    def test_statistical_functions(self):
        """통계 함수 테스트"""
        data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

        # 기본 통계량 테스트
        self.assertEqual(np.mean(data), 5.5)
        self.assertEqual(np.median(data), 5.5)
        self.assertAlmostEqual(np.std(data), 2.8722813232690143, places=5)

        # 분위수 테스트
        q25 = np.percentile(data, 25)
        q75 = np.percentile(data, 75)
        self.assertEqual(q25, 3.25)
        self.assertEqual(q75, 7.75)

    def test_array_manipulation(self):
        """배열 조작 테스트"""
        # 배열 reshape 테스트
        arr = np.arange(12)
        reshaped = arr.reshape(3, 4)
        self.assertEqual(reshaped.shape, (3, 4))

        # 배열 연결 테스트
        arr1 = np.array([1, 2, 3])
        arr2 = np.array([4, 5, 6])
        concatenated = np.concatenate([arr1, arr2])
        expected = np.array([1, 2, 3, 4, 5, 6])
        np.testing.assert_array_equal(concatenated, expected)

        # 배열 분할 테스트
        split_arrays = np.split(concatenated, 2)
        self.assertEqual(len(split_arrays), 2)
        self.assertEqual(len(split_arrays[0]), 3)


class TestDataVisualization(unittest.TestCase):
    """데이터 시각화 테스트 클래스"""

    def setUp(self):
        """테스트 설정"""
        try:
            import matplotlib.pyplot as plt
            import seaborn as sns

            self.plt = plt
            self.sns = sns
            self.visualization_available = True
        except ImportError:
            self.visualization_available = False

    def test_basic_plots(self):
        """기본 플롯 테스트"""
        if not self.visualization_available:
            self.skipTest("시각화 라이브러리가 설치되지 않았습니다.")

        # 라인 플롯 테스트
        fig, ax = self.plt.subplots()
        x = np.linspace(0, 10, 100)
        y = np.sin(x)
        ax.plot(x, y)

        self.assertIsNotNone(fig)
        self.plt.close(fig)

        # 산점도 테스트
        fig, ax = self.plt.subplots()
        x = np.random.randn(50)
        y = np.random.randn(50)
        ax.scatter(x, y)

        self.assertIsNotNone(fig)
        self.plt.close(fig)


def run_tests():
    """테스트 실행 함수"""
    # 테스트 스위트 생성
    test_suite = unittest.TestSuite()

    # 테스트 클래스 추가
    test_suite.addTest(unittest.makeSuite(TestAICoreLibraries))
    test_suite.addTest(unittest.makeSuite(TestDataVisualization))

    # 테스트 실행
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(test_suite)

    # 결과 출력
    print(f"\n=== 테스트 결과 ===")
    print(f"실행된 테스트: {result.testsRun}")
    print(f"실패한 테스트: {len(result.failures)}")
    print(f"오류가 발생한 테스트: {len(result.errors)}")

    if result.failures:
        print("\n실패한 테스트:")
        for test, error in result.failures:
            print(f"- {test}: {error}")

    if result.errors:
        print("\n오류가 발생한 테스트:")
        for test, error in result.errors:
            print(f"- {test}: {error}")

    return result.wasSuccessful()


if __name__ == "__main__":
    # 직접 실행 시 테스트 수행
    success = run_tests()

    if success:
        print("\n모든 테스트가 성공적으로 완료되었습니다! ✅")
    else:
        print("\n일부 테스트가 실패했습니다. ❌")
        sys.exit(1)
