from __future__ import annotations

import argparse
import hashlib
import json
import os
import sqlite3
import tempfile
import unittest
from contextlib import closing
from pathlib import Path

import doc2md.cli as cli

ROOT = Path(__file__).resolve().parents[1]
FIX_IN = ROOT / "tests" / "fixtures" / "in"


class HistoryLoggingTest(unittest.TestCase):
    def setUp(self) -> None:
        self._env_backup = os.environ.get("DOC2MD_HISTORY_DB")

    def tearDown(self) -> None:
        if self._env_backup is None:
            os.environ.pop("DOC2MD_HISTORY_DB", None)
        else:
            os.environ["DOC2MD_HISTORY_DB"] = self._env_backup

    def _make_args(self) -> argparse.Namespace:
        return argparse.Namespace(
            format=None,
            engine="pdfminer",
            output=None,
            preview=False,
            diff=False,
            yes=False,
            stats=False,
            profile_report=None,
            theme="auto",
            quiet=True,
            debug=False,
            csv_na="",
            csv_float_format=None,
            ocr=False,
            ocr_mode="never",
            ocr_lang="es",
            ocr_device=None,
            ocr_render_scale=2.0,
            ocr_min_score=None,
        )

    def test_history_logged_for_conversion(self) -> None:
        input_path = FIX_IN / "sample.csv"
        output_path = ROOT / "docs_out" / "sample.csv.md"
        if output_path.exists():
            output_path.unlink()

        with tempfile.TemporaryDirectory() as tmpdir:
            db_path = Path(tmpdir) / "history.db"
            os.environ["DOC2MD_HISTORY_DB"] = str(db_path)

            args = self._make_args()

            def debug(_msg: str) -> None:
                return

            exit_code = cli._run_conversion([input_path], args, debug)
            self.assertEqual(exit_code, 0)
            self.assertTrue(output_path.exists())

            expected_input_hash = hashlib.sha256(input_path.read_bytes()).hexdigest()
            output_bytes = output_path.read_bytes()
            expected_output_hash = hashlib.sha256(output_bytes).hexdigest()

            with closing(sqlite3.connect(db_path)) as conn:
                run = conn.execute(
                    "SELECT status, engine, format, exit_code, options_json FROM runs"
                ).fetchone()
                self.assertIsNotNone(run)
                self.assertEqual(run[0], "success")
                self.assertEqual(run[1], "pdfminer")
                self.assertIsNone(run[2])
                self.assertEqual(run[3], 0)
                options = json.loads(run[4])
                self.assertEqual(options["engine"], "pdfminer")

                input_row = conn.execute(
                    "SELECT path, sha256 FROM inputs"
                ).fetchone()
                self.assertIsNotNone(input_row)
                self.assertEqual(Path(input_row[0]).name, "sample.csv")
                self.assertEqual(input_row[1], expected_input_hash)

                output_row = conn.execute(
                    "SELECT path, bytes, sha256, written FROM outputs"
                ).fetchone()
                self.assertIsNotNone(output_row)
                self.assertEqual(Path(output_row[0]).name, "sample.csv.md")
                self.assertEqual(output_row[1], len(output_bytes))
                self.assertEqual(output_row[2], expected_output_hash)
                self.assertEqual(output_row[3], 1)

        if output_path.exists():
            output_path.unlink()


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