"""
Disaster Recovery tests
========================

Verify backup and restore procedures work correctly.
These tests may require SSH access to production/staging.
"""

import os
import subprocess
from pathlib import Path

import pytest

pytestmark = pytest.mark.dr

PROJECT_ROOT = Path(__file__).parent.parent.parent
STAGING_HOST = os.environ.get('STAGING_HOST', 'maciejpi@10.22.68.251')
PROD_HOST = os.environ.get('PROD_HOST', 'maciejpi@10.22.68.249')


def ssh_command(host: str, cmd: str, timeout: int = 60) -> tuple[int, str, str]:
    """Execute SSH command."""
    result = subprocess.run(
        ['ssh', host, cmd],
        capture_output=True,
        text=True,
        timeout=timeout
    )
    return result.returncode, result.stdout, result.stderr


class TestDRScripts:
    """Tests for DR scripts availability."""

    def test_dr_restore_script_exists(self):
        """DR restore script should exist locally."""
        script = PROJECT_ROOT / 'scripts' / 'dr-restore.sh'
        assert script.exists(), f"DR restore script not found: {script}"

    def test_dr_restore_script_executable(self):
        """DR restore script should be executable."""
        script = PROJECT_ROOT / 'scripts' / 'dr-restore.sh'

        if not script.exists():
            pytest.skip("DR restore script not found")

        # Check if it has executable permission
        assert os.access(script, os.X_OK), "DR restore script is not executable"

    def test_dr_playbook_exists(self):
        """DR playbook documentation should exist."""
        playbook = PROJECT_ROOT / 'docs' / 'DR-PLAYBOOK.md'
        assert playbook.exists(), f"DR playbook not found: {playbook}"


class TestBackupAvailability:
    """Tests for backup availability on production."""

    @pytest.mark.slow
    def test_hourly_backup_available(self):
        """Hourly backup should be available on production."""
        returncode, stdout, stderr = ssh_command(
            PROD_HOST,
            'ls -la /var/backups/nordabiz/hourly/ | tail -3'
        )

        assert returncode == 0, f"Failed to list hourly backups: {stderr}"
        assert 'nordabiz_' in stdout, "No hourly backups found"

    @pytest.mark.slow
    def test_daily_backup_available(self):
        """Daily backup should be available on production."""
        returncode, stdout, stderr = ssh_command(
            PROD_HOST,
            'ls -la /var/backups/nordabiz/daily/ | tail -3'
        )

        assert returncode == 0, f"Failed to list daily backups: {stderr}"
        assert 'nordabiz_' in stdout, "No daily backups found"


class TestRestoreOnStaging:
    """Tests for restore procedure on staging."""

    @pytest.mark.slow
    def test_can_copy_backup_to_staging(self):
        """Should be able to copy backup from prod to staging."""
        # Get latest backup filename
        returncode, stdout, _ = ssh_command(
            PROD_HOST,
            'ls -t /var/backups/nordabiz/hourly/ | head -1'
        )

        if returncode != 0 or not stdout.strip():
            pytest.skip("No backup available on production")

        backup_file = stdout.strip()

        # Try to copy to staging (dry run - just check connectivity)
        returncode, stdout, stderr = ssh_command(
            STAGING_HOST,
            f'scp -o StrictHostKeyChecking=no {PROD_HOST}:/var/backups/nordabiz/hourly/{backup_file} /tmp/ && echo OK'
        )

        # This might fail due to SSH key issues - that's expected in CI
        if returncode != 0:
            pytest.skip(f"Cannot copy backup to staging: {stderr}")

        assert 'OK' in stdout

    @pytest.mark.slow
    def test_restore_script_runs_on_staging(self):
        """Restore script should run on staging."""
        # This is a destructive test - should only run on staging
        returncode, stdout, stderr = ssh_command(
            STAGING_HOST,
            'test -x /var/www/nordabiznes/scripts/dr-restore.sh && echo OK'
        )

        if returncode != 0:
            pytest.skip("DR restore script not available on staging")

        assert 'OK' in stdout


class TestHealthAfterRestore:
    """Tests for application health after restore."""

    @pytest.mark.slow
    def test_staging_health_check(self):
        """Staging should respond to health check."""
        import requests

        staging_url = os.environ.get('STAGING_URL', 'https://staging.nordabiznes.pl')

        try:
            response = requests.get(f'{staging_url}/health', timeout=10)
            assert response.status_code == 200
            assert response.json().get('status') == 'ok'
        except requests.exceptions.RequestException as e:
            pytest.skip(f"Staging not accessible: {e}")

    @pytest.mark.slow
    def test_staging_database_has_data(self):
        """Staging database should have company data after restore."""
        import requests

        staging_url = os.environ.get('STAGING_URL', 'https://staging.nordabiznes.pl')

        try:
            response = requests.get(f'{staging_url}/api/companies', timeout=10)
            assert response.status_code == 200

            data = response.json()
            assert len(data) > 0, "Staging database appears empty"
        except requests.exceptions.RequestException as e:
            pytest.skip(f"Staging not accessible: {e}")
