import json
import tempfile
import unittest
from pathlib import Path
import app


class HabitsTest(unittest.TestCase):
    def test_roundtrip_and_title_change(self):
        with tempfile.TemporaryDirectory() as folder:
            path = Path(folder) / "habits.json"
            rows = app.load(path)
            rows[1]["done"] = True
            app.save(path, rows)
            loaded = app.load(path)
            self.assertEqual(app.summary(loaded), (1, 3))
            self.assertFalse(loaded[0]["done"])
            self.assertTrue(loaded[1]["done"])
            self.assertNotIn("title", json.loads(path.read_text())[0])

    def test_invalid_status_and_id(self):
        with tempfile.TemporaryDirectory() as folder:
            path = Path(folder) / "habits.json"
            for payload in [[], [{"id": 1, "done": True}] * 3,
                            [{"id": i, "done": "false"} for i in (1, 2, 3)],
                            [{"id": i, "done": False} for i in (1, 2, 99)]]:
                text = json.dumps(payload)
                path.write_text(text, encoding="utf-8")
                with self.assertRaises(ValueError):
                    app.load(path)
                self.assertEqual(path.read_text(encoding="utf-8"), text)

    def test_corrupt_file_preserved(self):
        with tempfile.TemporaryDirectory() as folder:
            path = Path(folder) / "habits.json"
            path.write_text("{rusak", encoding="utf-8")
            with self.assertRaises(ValueError):
                app.load(path)
            self.assertEqual(path.read_text(encoding="utf-8"), "{rusak")

    def test_gui_independent_checkboxes_and_reset(self):
        import tkinter as tk
        with tempfile.TemporaryDirectory() as folder:
            path = Path(folder) / "habits.json"
            root = tk.Tk()
            root.withdraw()
            try:
                view = app.build_window(root, path)
                view["checks"][2].invoke()
                self.assertEqual([r["done"] for r in view["rows"]], [False, True, False])
                view["buttons"]["Simpan"].invoke()
                view["buttons"]["Reset"].invoke()
                self.assertEqual(app.summary(view["rows"]), (0, 3))
                view["buttons"]["Muat"].invoke()
                self.assertEqual(app.summary(view["rows"]), (1, 3))
                root.update_idletasks()
            finally:
                root.destroy()


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