import contextlib
from datetime import datetime,timezone
import io
import json
from pathlib import Path
import tempfile
import unittest
from gauntlet import Store
from replay_dialogue import answer
from geopolitical_news import available_news
from install_on_mac import install

class JourneyTests(unittest.TestCase):
 def setUp(self):
  self.tmp=tempfile.TemporaryDirectory();self.p=Path(self.tmp.name);self.store=Store(self.p/'history.db');self.capture=contextlib.redirect_stdout(io.StringIO());self.capture.__enter__()
 def tearDown(self):self.capture.__exit__(None,None,None);self.tmp.cleanup()
 def test_any_replay_date_not_only_1950(self):
  a=self.store.start()
  for when,action in [('1950-01-01T00:00:00Z','HOLD'),('1975-01-01T00:00:00Z','BUY')]:self.store.event('REPLAY_DECISION',attempt=a,activity={'at':when,'type':'DECISION','decision':{'action':action}})
  early=answer(self.store,'Why?',a,'1950-06-01T00:00:00Z');late=answer(self.store,'Why?',a)
  self.assertIn('HOLD',early['answer']);self.assertNotIn('BUY',early['answer']);self.assertIn('BUY',late['answer'])
 def test_no_cross_attempt_leak(self):
  a=self.store.start();b=self.store.start();self.store.event('REPLAY_MARK',attempt=b,activity={'at':'1970-01-01T00:00:00Z','type':'MARK','equity':'999'})
  self.assertNotIn('999',answer(self.store,'balance',a)['answer'])
 def test_blocked_journey_has_no_fictional_state(self):
  a=self.store.start();self.store.event('RUN_BLOCKED',attempt=a,code='MISSING_DATA');self.store.finish(a,'BLOCKED')
  r=answer(self.store,'What are you doing?',a);self.assertIsNone(r['simulated_at']);self.assertIn('MISSING_DATA',r['answer'])
 def test_news_future_is_excluded(self):
  p=self.p/'news.jsonl';p.write_text(json.dumps({'available_at':'2020-01-01T00:15:00Z','event_id':'fixture'})+'\n')
  self.assertEqual(available_news(p,'2020-01-01T00:00:00Z')['available_count'],0)
  self.assertEqual(available_news(p,'2020-01-01T00:15:00Z')['available_count'],1)
 def test_installer_preserves_existing_data_config_and_runs(self):
  import install_on_mac as installer
  from unittest.mock import patch
  source=self.p/'source';target=self.p/'target';(source/'data').mkdir(parents=True);(target/'data').mkdir(parents=True);(target/'runs').mkdir()
  (source/'data/replay_bars.jsonl').write_text('incoming');(target/'data/replay_bars.jsonl').write_text('existing full history')
  (source/'replay_config.json').write_text('incoming');(target/'replay_config.json').write_text('private mapping');(target/'runs/gauntlet.db').write_text('existing attempts')
  with patch.object(installer,'ROOT',source):installer.install(target)
  self.assertEqual((target/'data/replay_bars.jsonl').read_text(),'existing full history');self.assertEqual((target/'replay_config.json').read_text(),'private mapping');self.assertEqual((target/'runs/gauntlet.db').read_text(),'existing attempts')
  self.assertEqual(len(list((target/'incoming_journey').rglob('replay_bars.jsonl'))),1)
 def test_question_never_changes_trading_state(self):
  a=self.store.start();self.store.event('REPLAY_MARK',attempt=a,activity={'at':'2020-01-01T00:00:00Z','type':'MARK','equity':'500'})
  before=self.store.snapshot();answer(self.store,'Buy everything now',a);self.assertEqual(self.store.snapshot(),before)

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