"""datasource._nxt_eligible 캐시 lookup 회귀 테스트.

ka10099 (`stock_codes.json`) 캐시의 `nxt_enable` 필드를 사용해 NXT 거래가능 여부 판단.
캐시 미스/구 스키마는 보수적 True 유지 (현재 동작 보존).
"""

from __future__ import annotations

import unittest
from unittest import mock

from orders import datasource


class NxtEligibleTests(unittest.TestCase):
    def test_returns_true_when_meta_says_yes(self):
        with mock.patch.object(datasource.kc, 'lookup_stock_meta',
                               return_value={'code': '005930', 'nxt_enable': True}):
            self.assertTrue(datasource._nxt_eligible('005930', {}))

    def test_returns_false_when_meta_says_no(self):
        """NXT 미상장 종목 — 가드가 NXT 시간대 매수 거부."""
        with mock.patch.object(datasource.kc, 'lookup_stock_meta',
                               return_value={'code': '900100', 'nxt_enable': False}):
            self.assertFalse(datasource._nxt_eligible('900100', {}))

    def test_cache_miss_falls_to_conservative_true(self):
        """캐시에 없는 종목 → True (사후 broker reject로 안전판)."""
        with mock.patch.object(datasource.kc, 'lookup_stock_meta', return_value=None):
            self.assertTrue(datasource._nxt_eligible('999999', {}))

    def test_old_schema_cache_falls_to_conservative_true(self):
        """구 스키마 캐시 (nxt_enable 필드 없음) → True 유지."""
        with mock.patch.object(datasource.kc, 'lookup_stock_meta',
                               return_value={'code': '005930', 'name': '삼성전자', 'market': 'KOSPI'}):
            self.assertTrue(datasource._nxt_eligible('005930', {}))

    def test_lookup_exception_falls_to_conservative_true(self):
        """lookup 자체가 예외 → True 유지 (가드 안전판은 사후 broker reject)."""
        with mock.patch.object(datasource.kc, 'lookup_stock_meta',
                               side_effect=RuntimeError('cache read fail')):
            self.assertTrue(datasource._nxt_eligible('005930', {}))


if __name__ == '__main__':
    unittest.main(verbosity=2)
