"""Run with python3 -m unittest -v test_query_in.py."""
from contextlib import closing
import sqlite3
import subprocess
import sys
import unittest

from query_in import demo_connection, find_jobs


class QueryTests(unittest.TestCase):
    def test_empty_skips_select(self):
        with closing(demo_connection()) as con:
            trace = []
            con.set_trace_callback(trace.append)
            self.assertEqual(find_jobs(con, []), [])
            self.assertEqual(trace, [])

    def test_single_quote_duplicate_and_missing(self):
        with closing(demo_connection()) as con:
            rows = find_jobs(con, ["o'reilly", "alpha", "alpha", "missing"], batch_size=1)
            self.assertEqual([r["name"] for r in rows], ["alpha", "o'reilly"])

    def test_status_filter(self):
        with closing(demo_connection()) as con:
            self.assertEqual(find_jobs(con, ["alpha", "beta"], "done"),
                             [{"name": "beta", "status": "done"}])

    def test_sql_text_is_just_data(self):
        with closing(demo_connection()) as con:
            self.assertEqual(find_jobs(con, ["x') OR 1=1 --"]), [])
            self.assertEqual(con.execute("SELECT count(*) FROM jobs").fetchone(), (4,))

    def test_lowered_limit_and_reserved_parameter(self):
        with closing(demo_connection()) as con:
            category = sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER
            previous = con.setlimit(category, 3)
            trace = []
            con.set_trace_callback(trace.append)
            try:
                rows = find_jobs(con, ["alpha", "beta", "gamma", "o'reilly"], batch_size=500)
                self.assertEqual(len(rows), 3)
                self.assertEqual(len(trace), 2)
            finally:
                con.setlimit(category, previous)
            self.assertEqual(con.getlimit(category), previous)

    def test_no_parameter_room(self):
        with closing(demo_connection()) as con:
            con.setlimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER, 1)
            with self.assertRaisesRegex(ValueError, "no room"):
                find_jobs(con, ["alpha"])

    def test_invalid_input(self):
        with closing(demo_connection()) as con:
            with self.assertRaises(ValueError):
                find_jobs(con, [1])
            with self.assertRaises(ValueError):
                find_jobs(con, ["alpha"], batch_size=0)

    def test_cli(self):
        from pathlib import Path
        script = str(Path(__file__).with_name("query_in.py"))
        ok = subprocess.run([sys.executable, script, "alpha"], capture_output=True, text=True)
        self.assertEqual(ok.returncode, 0)
        self.assertIn('"name": "alpha"', ok.stdout)
        bad = subprocess.run([sys.executable, script, "--batch-size", "0"],
                             capture_output=True, text=True)
        self.assertEqual(bad.returncode, 2)
        self.assertEqual(bad.stdout, "")


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