#!/usr/bin/env python3
"""code_reviewer.py 단위 테스트"""

import os
import sys
import tempfile
import unittest
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))

from code_reviewer import CodeReviewer


class TestCodeReviewer(unittest.TestCase):
    """Code Reviewer 테스트"""

    def setUp(self):
        """테스트 설정"""
        self.reviewer = CodeReviewer()

    def test_reviewer_initialized(self):
        """리뷰어가 초기화되었는지 확인"""
        self.assertIsNotNone(self.reviewer)

    def test_review_normal_file(self):
        """정상 파일 검토"""
        with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
            f.write("# Normal code\npass\n")
            temp_path = f.name

        try:
            result = self.reviewer.review(temp_path)

            self.assertIn("risk_level", result)
            self.assertIn("vulnerabilities", result)
            self.assertIn("passed", result)
            self.assertIn(result["risk_level"], ["low", "medium", "high", "critical"])
        finally:
            os.unlink(temp_path)

    def test_review_vulnerable_file_hardcoded_secret(self):
        """취약점 파일 검토 - 하드코딩 시크릿"""
        with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
            f.write("password = '123456'\n")
            temp_path = f.name

        try:
            result = self.reviewer.review(temp_path)

            self.assertIn("vulnerability_count", result)
            self.assertGreater(result["vulnerability_count"], 0)
            self.assertFalse(result["passed"])
        finally:
            os.unlink(temp_path)

    def test_review_vulnerable_file_sql_injection(self):
        """취약점 파일 검토 - SQL 인젝션"""
        with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
            f.write("query = 'SELECT * FROM users WHERE id=' + user_id\n")
            temp_path = f.name

        try:
            result = self.reviewer.review(temp_path)

            self.assertIn("vulnerability_count", result)
            # SQL Injection 패턴이 감지되어야 함
            vuln_types = [v["type"] for v in result.get("vulnerabilities", [])]
            self.assertTrue(any("SQL" in t for t in vuln_types) or result["vulnerability_count"] > 0)
        finally:
            os.unlink(temp_path)

    def test_review_nonexistent_file(self):
        """존재하지 않는 파일 검토"""
        result = self.reviewer.review("/nonexistent/file.py")

        # 파일 로드 실패 시 error와 risk_level 반환
        self.assertIn("error", result)
        self.assertIn(result["risk_level"], ["unknown", "critical"])

    def test_check_tool_available_python3(self):
        """도구 가용성 체크 - python3"""
        result = self.reviewer._check_tool_available("python3")
        self.assertTrue(result)

    def test_check_tool_available_nonexistent(self):
        """도구 가용성 체크 - 존재하지 않는 도구"""
        result = self.reviewer._check_tool_available("nonexistent_tool_12345")
        self.assertFalse(result)

    def test_get_severity_sql_injection(self):
        """심각도 확인 - SQL Injection"""
        severity = self.reviewer._get_severity("SQL Injection")
        self.assertEqual(severity, "high")

    def test_get_severity_command_injection(self):
        """심각도 확인 - Command Injection"""
        severity = self.reviewer._get_severity("Command Injection")
        self.assertEqual(severity, "critical")

    def test_get_severity_unknown(self):
        """심각도 확인 - 알 수 없는 타입"""
        severity = self.reviewer._get_severity("Unknown Type")
        self.assertEqual(severity, "low")

    def test_assess_architecture_risks_large_file(self):
        """아키텍처 리스크 - 큰 파일"""
        # 201줄 이상의 파일
        large_content = "\n".join([f"# Line {i}" for i in range(201)])
        issues = self.reviewer._assess_architecture_risks(large_content)

        large_file_issues = [i for i in issues if i["type"] == "Large File"]
        self.assertEqual(len(large_file_issues), 1)
        self.assertEqual(large_file_issues[0]["severity"], "medium")

    def test_assess_architecture_risks_multiple_classes(self):
        """아키텍처 리스크 - 여러 클래스"""
        content = """
class Class1:
    pass

class Class2:
    pass

class Class3:
    pass

class Class4:
    pass
"""
        issues = self.reviewer._assess_architecture_risks(content)

        multi_class_issues = [i for i in issues if i["type"] == "Multiple Classes"]
        self.assertEqual(len(multi_class_issues), 1)


if __name__ == "__main__":
    unittest.main()
