"""
기본 테스트 모듈
"""
import pytest
import requests
from app.services.negotiation_env import NegotiationEnvironment
from app.services.qtable_learner import QTableLearner, ExperienceBuffer
from app.models.schemas import CardType, ScenarioType, PriceZoneType


class TestNegotiationEnvironment:
    """협상 환경 테스트"""

    def setup_method(self):
        self.env = NegotiationEnvironment()

    def test_reward_calculation(self):
        """보상 계산 테스트"""
        reward, weight = self.env.calculate_reward(
            scenario=ScenarioType.A,
            price_zone=PriceZoneType.PZ1,
            anchor_price=100,
            proposed_price=95,
            is_end=True
        )

        assert reward > 0
        assert 0 <= weight <= 1

    def test_price_zone_determination(self):
        """가격 구간 결정 테스트"""
        # 목표가 이하
        zone = self.env.get_price_zone(90, 100)
        assert zone == PriceZoneType.PZ1

        # 중간 구간
        zone = self.env.get_price_zone(110, 100)
        assert zone == PriceZoneType.PZ2

        # 높은 구간
        zone = self.env.get_price_zone(150, 100)
        assert zone == PriceZoneType.PZ3

    def test_opponent_response_simulation(self):
        """상대방 응답 시뮬레이션 테스트"""
        price = self.env.simulate_opponent_response(
            current_card=CardType.C1,
            scenario=ScenarioType.A,
            anchor_price=100,
            step=0
        )

        assert price > 0
        assert isinstance(price, float)


class TestQTableLearner:
    """Q-Table 학습 테스트"""

    def setup_method(self):
        states = ["S1", "S2", "S3"]
        actions = [CardType.C1, CardType.C2]
        self.learner = QTableLearner(states, actions)

    def test_initialization(self):
        """초기화 테스트"""
        assert self.learner.q_table.shape == (3, 2)
        assert (self.learner.q_table == 0).all().all()

    def test_q_value_update(self):
        """Q값 업데이트 테스트"""
        td_error = self.learner.update_q_value(
            state="S1",
            action=CardType.C1,
            reward=1.0,
            next_state="S2",
            done=False
        )

        assert td_error != 0
        assert self.learner.get_q_value("S1", CardType.C1) != 0

    def test_action_selection(self):
        """행동 선택 테스트"""
        # 초기 상태에서는 무작위 선택
        action, is_exploration = self.learner.select_action("S1")
        assert action in [CardType.C1, CardType.C2]

        # Q값 설정 후 최적 행동 선택
        self.learner.set_q_value("S1", CardType.C2, 1.0)
        optimal_action = self.learner.get_optimal_action("S1")
        assert optimal_action == CardType.C2


class TestExperienceBuffer:
    """경험 버퍼 테스트"""

    def setup_method(self):
        self.buffer = ExperienceBuffer(max_size=10)

    def test_add_experience(self):
        """경험 추가 테스트"""
        self.buffer.add_experience(
            state="S1",
            action=CardType.C1,
            reward=1.0,
            next_state="S2",
            done=False
        )

        assert self.buffer.size() == 1

    def test_buffer_overflow(self):
        """버퍼 오버플로우 테스트"""
        # 최대 크기보다 많이 추가
        for i in range(15):
            self.buffer.add_experience(
                state=f"S{i}",
                action=CardType.C1,
                reward=1.0,
                next_state=f"S{i+1}",
                done=False
            )

        # 최대 크기 유지
        assert self.buffer.size() == 10

    def test_sampling(self):
        """샘플링 테스트"""
        # 경험 추가
        for i in range(5):
            self.buffer.add_experience(
                state=f"S{i}",
                action=CardType.C1,
                reward=1.0,
                next_state=f"S{i+1}",
                done=False
            )

        # 배치 샘플링
        batch = self.buffer.sample_batch(3)
        assert len(batch) == 3


# API 통합 테스트 (선택사항)
class TestAPIIntegration:
    """API 통합 테스트"""

    def test_health_check(self):
        """헬스 체크 테스트"""
        try:
            response = requests.get("http://localhost:8000/api/v1/health")
            assert response.status_code == 200
            data = response.json()
            assert data["status"] == "healthy"
        except requests.exceptions.ConnectionError:
            pytest.skip("API 서버가 실행되지 않음")

    def test_reward_calculation_endpoint(self):
        """보상 계산 엔드포인트 테스트"""
        try:
            payload = {
                "scenario": "A",
                "price_zone": "PZ1",
                "anchor_price": 100,
                "proposed_price": 95,
                "is_end": True
            }

            response = requests.post(
                "http://localhost:8000/api/v1/reward/calculate",
                json=payload
            )

            assert response.status_code == 200
            data = response.json()
            assert "reward" in data
            assert "weight" in data
        except requests.exceptions.ConnectionError:
            pytest.skip("API 서버가 실행되지 않음")
