#!/usr/bin/env python3
"""
Test backwards compatibility for encrypted databases.

This test ensures that databases created with previous versions can still
be opened with the current version. This prevents breaking changes like
salt modifications from going undetected.

The key tests are:
1. TestSaltStability - Fast tests that verify encryption constants haven't changed
2. TestBackwardsCompatibility - Slow test that actually installs previous PyPI version

The salt stability tests run in CI and catch 99% of breaking changes.
The full backwards compatibility test can be run manually with:
    pytest tests/database/test_backwards_compatibility.py -m slow --run-slow
"""

import os
import subprocess
import sys
import tempfile
from pathlib import Path

import pytest


# Path to the script that creates a database using the installed package
# This is in a separate file for better IDE support (syntax highlighting, linting)
CREATE_DB_SCRIPT_PATH = (
    Path(__file__).parent / "scripts" / "create_compat_db.py"
)


class TestBackwardsCompatibility:
    """Test that current version can open databases from previous versions."""

    @pytest.fixture
    def temp_dir(self):
        """Create a temporary directory for test databases."""
        with tempfile.TemporaryDirectory() as tmpdir:
            yield Path(tmpdir)

    def get_previous_version(self) -> str:
        """Get the previous version number from PyPI."""
        result = subprocess.run(
            [
                sys.executable,
                "-m",
                "pip",
                "index",
                "versions",
                "local-deep-research",
            ],
            capture_output=True,
            text=True,
        )

        if result.returncode != 0:
            # Fallback: try to get from pip show
            result = subprocess.run(
                [sys.executable, "-m", "pip", "show", "local-deep-research"],
                capture_output=True,
                text=True,
            )
            # Can't determine previous version
            pytest.skip("Could not determine previous version from PyPI")

        # Parse versions from output
        # Output format: "local-deep-research (1.3.21)\nAvailable versions: 1.3.21, 1.3.20, ..."
        for line in result.stdout.split("\n"):
            if "Available versions:" in line:
                versions = line.split(":")[1].strip().split(", ")
                if len(versions) >= 2:
                    return versions[1]  # Second version is the previous one

        pytest.skip("Could not find previous version")

    @pytest.mark.slow
    @pytest.mark.timeout(600)  # 10 minutes - installing PyPI package takes time
    @pytest.mark.skipif(
        os.environ.get("RUN_SLOW_TESTS") != "true",
        reason="Slow test - set RUN_SLOW_TESTS=true to run",
    )
    def test_open_database_from_previous_version(self, temp_dir, monkeypatch):
        """
        Test that we can open a database created with the previous PyPI version.

        This test:
        1. Installs the previous version in an isolated venv
        2. Creates a database using that version
        3. Verifies the current version can open it and read data
        """
        # Get previous version
        try:
            previous_version = self.get_previous_version()
        except Exception as e:
            pytest.skip(f"Could not get previous version: {e}")

        # Create isolated venv for previous version
        venv_dir = temp_dir / "prev_venv"
        db_dir = temp_dir / "databases"
        db_dir.mkdir()

        # Create venv
        result = subprocess.run(
            [sys.executable, "-m", "venv", str(venv_dir)],
            capture_output=True,
            text=True,
        )
        if result.returncode != 0:
            pytest.skip(f"Could not create venv: {result.stderr}")

        # Get venv python
        if sys.platform == "win32":
            venv_python = venv_dir / "Scripts" / "python.exe"
        else:
            venv_python = venv_dir / "bin" / "python"

        # Install previous version (with timeout)
        # Package has many dependencies, needs sufficient time
        result = subprocess.run(
            [
                str(venv_python),
                "-m",
                "pip",
                "install",
                f"local-deep-research=={previous_version}",
                "--quiet",
            ],
            capture_output=True,
            text=True,
            timeout=600,  # 10 minute timeout - package has many dependencies
        )
        if result.returncode != 0:
            pytest.skip(f"Could not install previous version: {result.stderr}")

        # Create database with previous version
        username = "compat_test_user"
        password = "CompatTestPass123!"

        # Copy the script to temp dir (script is in separate file for IDE support)
        script_file = temp_dir / "create_db.py"
        script_file.write_text(CREATE_DB_SCRIPT_PATH.read_text())

        result = subprocess.run(
            [
                str(venv_python),
                str(script_file),
                str(db_dir),
                username,
                password,
            ],
            capture_output=True,
            text=True,
            timeout=60,
        )
        if result.returncode != 0:
            pytest.fail(
                f"Could not create database with previous version: {result.stderr}"
            )

        # Now test opening with current version
        monkeypatch.setattr(
            "local_deep_research.database.encrypted_db.get_data_directory",
            lambda: db_dir,
        )

        from local_deep_research.database.encrypted_db import (
            DatabaseManager,
        )
        from local_deep_research.database.models import UserSettings

        manager = DatabaseManager()
        manager.data_dir = db_dir / "encrypted_databases"

        # Try to open the database
        engine = manager.open_user_database(username, password)
        assert engine is not None, (
            f"Failed to open database created with version {previous_version}. "
            "This likely means a breaking change was introduced (e.g., salt change)."
        )

        # Verify we can read the data
        session = manager.get_session(username)
        setting = (
            session.query(UserSettings)
            .filter_by(key="test.backwards_compat")
            .first()
        )

        assert setting is not None, (
            "Could not read data from previous version database"
        )
        assert setting.value["version"] == "previous"
        assert setting.value["test"] is True

        session.close()
        manager.close_user_database(username)


# Note: Salt stability tests have been moved to test_encryption_constants.py
# This file now only contains the slow PyPI backwards compatibility test.


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
