from pathlib import Path
import hashlib
import sqlite3
import tempfile
import unittest
from unittest.mock import patch
import purge_test_data as purge

class Tests(unittest.TestCase):
    def setUp(self):
        self.tmp=tempfile.TemporaryDirectory();self.root=Path(self.tmp.name).resolve();(self.root/'generated').mkdir()
        self.db=self.root/'qzotic_pure_sandbox.db';c=sqlite3.connect(self.db)
        c.execute('PRAGMA foreign_keys=ON')
        c.execute('CREATE TABLE enterprise_portfolio(project_id INTEGER PRIMARY KEY AUTOINCREMENT,project_name TEXT UNIQUE,allocated_budget_cents INTEGER)')
        c.execute("INSERT INTO enterprise_portfolio VALUES(1,'BPA_TAX_FIRM_ANNUAL_AUDIT',4500000)")
        c.execute('CREATE TABLE remediation_lifecycle(id INTEGER PRIMARY KEY,associated_project TEXT REFERENCES enterprise_portfolio(project_name))')
        c.execute("INSERT INTO remediation_lifecycle VALUES(1,'BPA_TAX_FIRM_ANNUAL_AUDIT')")
        c.execute('CREATE TABLE notification_outbox(id INTEGER PRIMARY KEY,associated_project TEXT REFERENCES enterprise_portfolio(project_name))')
        c.execute('CREATE TABLE project_event_versions(project_name TEXT REFERENCES enterprise_portfolio(project_name))')
        c.execute('CREATE TABLE ingestion_journal(event_id TEXT)');c.execute("INSERT INTO ingestion_journal VALUES('frozen-event')")
        c.execute('CREATE TABLE audit_events(event_type TEXT,reference TEXT,recorded_at TEXT)')
        c.execute('CREATE TABLE consigliere_room_audits(notes TEXT)');c.execute("INSERT INTO consigliere_room_audits VALUES('retain')")
        c.commit();c.close();self.db.chmod(0o600)
        self.ledger=self.root/'generated/automated_irs_form_8949.json';self.ledger.write_text('[{"fictional":true}]')
        self.mock=patch.object(purge,'LEDGER_HASH',hashlib.sha256(self.ledger.read_bytes()).hexdigest());self.mock.start()
    def tearDown(self):self.mock.stop();self.tmp.cleanup()
    def test_preview_unchanged(self):
        before=self.db.read_bytes();r=purge.run(self.root)
        self.assertEqual(r['mode'],'PREVIEW');self.assertEqual(self.db.read_bytes(),before);self.assertTrue(self.ledger.exists())
    def test_apply_archives_and_preserves_history(self):
        original=self.ledger.read_bytes();r=purge.run(self.root,True);c=sqlite3.connect(self.db)
        self.assertEqual(c.execute('SELECT COUNT(*) FROM enterprise_portfolio').fetchone()[0],0)
        self.assertEqual(c.execute('SELECT COUNT(*) FROM remediation_lifecycle').fetchone()[0],0)
        self.assertEqual(c.execute('SELECT COUNT(*) FROM ingestion_journal').fetchone()[0],1)
        self.assertEqual(c.execute('SELECT notes FROM consigliere_room_audits').fetchone()[0],'retain');c.close()
        archive=Path(r['archive']);self.assertEqual((archive/'sample_ledger.json').read_bytes(),original);self.assertFalse(self.ledger.exists())
        restored=sqlite3.connect(archive/'operational_before.sqlite3');self.assertEqual(restored.execute('SELECT COUNT(*) FROM enterprise_portfolio').fetchone()[0],1);restored.close()
    def test_unknown_rows_block(self):
        c=sqlite3.connect(self.db);c.execute("INSERT INTO enterprise_portfolio VALUES(2,'REAL',100)");c.commit();c.close()
        with self.assertRaises(ValueError):purge.run(self.root,True)
        c=sqlite3.connect(self.db);self.assertEqual(c.execute('SELECT COUNT(*) FROM enterprise_portfolio').fetchone()[0],2);c.close()
    def test_modified_ledger_blocks_before_deletion(self):
        self.ledger.write_text('different')
        with self.assertRaises(ValueError):purge.run(self.root,True)
        c=sqlite3.connect(self.db);self.assertEqual(c.execute('SELECT COUNT(*) FROM enterprise_portfolio').fetchone()[0],1);c.close()
    def test_foreign_key_delete_order(self):
        purge.run(self.root,True);c=sqlite3.connect(self.db);self.assertEqual(c.execute('PRAGMA foreign_key_check').fetchall(),[]);c.close()
    def test_research_history_retained(self):
        p=self.root/'luxzia_research.db';c=sqlite3.connect(p)
        c.execute('CREATE TABLE lucxia_knowledge_history(notes TEXT)');c.execute("INSERT INTO lucxia_knowledge_history VALUES('research notes')")
        c.execute("CREATE TRIGGER prevent_delete BEFORE DELETE ON lucxia_knowledge_history BEGIN SELECT RAISE(ABORT,'retain'); END")
        c.execute('CREATE TABLE lucxia_fictional_scenarios(scenario_uid TEXT PRIMARY KEY)');c.execute("INSERT INTO lucxia_fictional_scenarios VALUES('SCEN_20261101_01')");c.commit();c.close();p.chmod(0o600)
        purge.run(self.root,True);c=sqlite3.connect(p);self.assertEqual(c.execute('SELECT COUNT(*) FROM lucxia_fictional_scenarios').fetchone()[0],0);self.assertEqual(c.execute('SELECT notes FROM lucxia_knowledge_history').fetchone()[0],'research notes');c.close()

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