#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Integration tests for the SQLiteStateManager and state persistence failure modes.
"""

import os
import sqlite3
import stat
import pytest
from pathlib import Path

import sys

sys.path.append(str(Path(__file__).parent.parent.parent / "sdk-examples" / "vendor-bridge"))
from api_to_otlp_bridge import MockVendorBridge, SQLiteStateManager
from mca_sdk.config import MCAConfig


@pytest.fixture
def state_db(tmp_path: Path) -> Path:
    """Fixture for a temporary SQLite database path."""
    return tmp_path / "state.db"


class TestStatePersistence:
    """Tests for state persistence failure modes."""

    def test_crash_and_restart_recovery(self, state_db: Path):
        """Verify that the bridge correctly resumes its count after a simulated crash."""
        # --- First run ---
        config1 = MCAConfig(
            service_name="test-vendor-bridge",
            vendor_api_url="http://localhost:8080/metrics",
            collector_endpoint="http://localhost:4318",
            vendor_bridge_state_file=str(state_db),
            vendor_bridge_max_iterations=2,  # Run for 2 iterations and then "crash"
        )
        bridge1 = MockVendorBridge(config1)
        bridge1._cumulative_predictions = 100
        bridge1._cumulative_errors = 10
        bridge1._state_manager.save_state({"cumulative_predictions": 100, "cumulative_errors": 10})
        bridge1.close()

        # --- Second run (simulating restart) ---
        config2 = MCAConfig(
            service_name="test-vendor-bridge",
            vendor_api_url="http://localhost:8080/metrics",
            collector_endpoint="http://localhost:4318",
            vendor_bridge_state_file=str(state_db),
        )
        bridge2 = MockVendorBridge(config2)

        # Verify that the state was loaded correctly
        assert bridge2._cumulative_predictions == 100
        assert bridge2._cumulative_errors == 10
        bridge2.close()

    def test_database_corruption_handling(self, state_db: Path, caplog):
        """Ensure the bridge handles a corrupted SQLite file gracefully."""
        # Create a corrupted database file
        with open(state_db, "w") as f:
            f.write("this is not a valid sqlite database")

        config = MCAConfig(
            service_name="test-vendor-bridge",
            vendor_api_url="http://localhost:8080/metrics",
            collector_endpoint="http://localhost:4318",
            vendor_bridge_state_file=str(state_db),
        )
        bridge = MockVendorBridge(config)

        # Verify that the bridge logged a warning and started fresh
        assert "Database file corrupted" in caplog.text
        assert "Deleting and recreating" in caplog.text
        assert bridge._cumulative_predictions == 0
        assert bridge._cumulative_errors == 0
        bridge.close()

    def test_write_permission_error_handling(self, state_db: Path, caplog):
        """Test the bridge's behavior with write-permission errors."""
        # Create the database and then make it read-only
        state_manager = SQLiteStateManager(str(state_db))
        state_manager.connect()
        state_manager.save_state({"cumulative_predictions": 1, "cumulative_errors": 1})
        state_manager.close()

        os.chmod(state_db, stat.S_IREAD)

        config = MCAConfig(
            service_name="test-vendor-bridge",
            vendor_api_url="http://localhost:8080/metrics",
            collector_endpoint="http://localhost:4318",
            vendor_bridge_state_file=str(state_db),
        )
        bridge = MockVendorBridge(config)

        # The bridge should load the state, but fail to save
        assert bridge._cumulative_predictions == 1
        assert bridge._cumulative_errors == 1

        # Simulate a poll that tries to save state
        bridge.transform_metrics(
            {
                "metrics": {
                    "predictions_since_last_poll": 10,
                    "errors_since_last_poll": 1,
                }
            }
        )

        # Verify that the error was logged
        assert "Failed to save state" in caplog.text
        assert "attempt to write a readonly database" in caplog.text

        # Cleanup
        os.chmod(state_db, stat.S_IWRITE)
        bridge.close()

    def test_max_iterations_shutdown(self, state_db: Path):
        """Verify that the bridge shuts down gracefully after max_iterations."""
        config = MCAConfig(
            service_name="test-vendor-bridge",
            vendor_api_url="http://localhost:8080/metrics",
            collector_endpoint="http://localhost:4318",
            vendor_bridge_state_file=str(state_db),
            vendor_bridge_max_iterations=3,
        )
        bridge = MockVendorBridge(config)
        bridge.start()
        bridge.wait_for_completion()

        stats = bridge.get_stats()
        assert stats["poll_count"] == 3
        assert not bridge.is_running()

        # Verify that the final state was saved
        state_manager = SQLiteStateManager(str(state_db))
        state_manager.connect()
        state = state_manager.load_state()
        state_manager.close()

        assert state.get("cumulative_predictions", 0) >= 0
        assert state.get("cumulative_errors", 0) >= 0
