from __future__ import annotations

import tempfile
import unittest
from pathlib import Path

from database import ReviewDatabase
from trade_journal import TradeJournalService


class TradeJournalTests(unittest.TestCase):
    def setUp(self) -> None:
        self.temp = tempfile.TemporaryDirectory()
        self.database = ReviewDatabase(Path(self.temp.name) / "review.db")
        self.owner = self.database.create_user("trade_owner", "salt", "hash")
        self.other = self.database.create_user("trade_other", "salt", "hash")
        self.service = TradeJournalService(self.database)

    def tearDown(self) -> None:
        self.temp.cleanup()

    @staticmethod
    def payload(**overrides):
        data = {
            "trade_date": "2026-07-22",
            "code": "002141",
            "name": "贤丰控股",
            "action": "buy",
            "price": 10.25,
            "quantity": 1000,
            "position_pct": 20,
            "pnl_amount": "",
            "pnl_pct": "",
            "thesis": "修复期低吸",
            "execution": "按计划成交",
            "emotion": "calm",
            "tags": "计划内，低吸",
        }
        data.update(overrides)
        return data

    def test_unrealized_entry_does_not_enter_win_rate(self):
        self.service.save(self.owner["id"], self.payload())
        result = self.service.list_entries(self.owner["id"])

        self.assertEqual(result["summary"]["total"], 1)
        self.assertEqual(result["summary"]["realized"], 0)
        self.assertIsNone(result["summary"]["win_rate"])
        self.assertEqual(result["items"][0]["tags"], ["计划内", "低吸"])

    def test_realized_entries_build_summary(self):
        self.service.save(
            self.owner["id"], self.payload(action="sell", pnl_amount=500, pnl_pct=5)
        )
        self.service.save(
            self.owner["id"],
            self.payload(code="600000", name="浦发银行", action="sell", pnl_amount=-200, pnl_pct=-2, position_pct=40),
        )
        result = self.service.list_entries(self.owner["id"])

        self.assertEqual(result["summary"]["realized"], 2)
        self.assertEqual(result["summary"]["win_rate"], 50.0)
        self.assertEqual(result["summary"]["pnl_amount"], 300.0)
        self.assertEqual(result["summary"]["average_position"], 30.0)

    def test_update_and_delete_require_ownership(self):
        trade_id = self.service.save(self.owner["id"], self.payload())
        with self.assertRaises(ValueError):
            self.service.save(
                self.other["id"], self.payload(id=trade_id, thesis="越权修改")
            )
        self.assertFalse(self.database.delete_trade_entry(self.other["id"], trade_id))

        self.service.save(
            self.owner["id"], self.payload(id=trade_id, thesis="复盘后修订")
        )
        self.assertEqual(
            self.service.list_entries(self.owner["id"])["items"][0]["thesis"],
            "复盘后修订",
        )
        self.assertTrue(self.database.delete_trade_entry(self.owner["id"], trade_id))
        self.assertEqual(self.service.list_entries(self.owner["id"])["summary"]["total"], 0)

    def test_entries_are_isolated_between_accounts(self):
        self.service.save(self.owner["id"], self.payload())
        self.assertEqual(self.service.list_entries(self.other["id"])["items"], [])


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