"""
Smoke tests for backup health
==============================

Verify that backups are being created and are valid.
These tests require SSH access to production server.

Usage:
    pytest tests/smoke/test_backup_health.py -v
"""

import os
import subprocess
from datetime import datetime, timedelta

import pytest

pytestmark = [pytest.mark.smoke, pytest.mark.dr]

# Production server
PROD_HOST = os.environ.get('PROD_HOST', 'maciejpi@10.22.68.249')
BACKUP_DIR = '/var/backups/nordabiz'


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


class TestBackupFreshness:
    """Tests for backup freshness."""

    @pytest.mark.slow
    def test_hourly_backup_exists(self):
        """Hourly backup from last 2 hours should exist."""
        returncode, stdout, stderr = ssh_command(
            f'ls -t {BACKUP_DIR}/hourly/ | head -1'
        )

        assert returncode == 0, f"SSH failed: {stderr}"
        assert stdout.strip(), "No hourly backup found"

        # Check file is recent
        returncode, stdout, _ = ssh_command(
            f'stat -c %Y {BACKUP_DIR}/hourly/$(ls -t {BACKUP_DIR}/hourly/ | head -1)'
        )

        if returncode == 0 and stdout.strip():
            file_time = int(stdout.strip())
            now = int(datetime.now().timestamp())
            age_hours = (now - file_time) / 3600

            assert age_hours < 2, f"Hourly backup is {age_hours:.1f} hours old (should be < 2)"

    @pytest.mark.slow
    def test_daily_backup_exists(self):
        """Daily backup from last 25 hours should exist."""
        returncode, stdout, stderr = ssh_command(
            f'ls -t {BACKUP_DIR}/daily/ | head -1'
        )

        assert returncode == 0, f"SSH failed: {stderr}"
        assert stdout.strip(), "No daily backup found"


class TestBackupSize:
    """Tests for backup file sizes."""

    @pytest.mark.slow
    def test_hourly_backup_size_reasonable(self):
        """Hourly backup should be at least 1MB (not empty/corrupt)."""
        returncode, stdout, stderr = ssh_command(
            f'du -b {BACKUP_DIR}/hourly/$(ls -t {BACKUP_DIR}/hourly/ | head -1) | cut -f1'
        )

        assert returncode == 0, f"SSH failed: {stderr}"

        size_bytes = int(stdout.strip())
        size_mb = size_bytes / (1024 * 1024)

        assert size_mb >= 1, f"Backup too small: {size_mb:.2f} MB (should be >= 1 MB)"

    @pytest.mark.slow
    def test_daily_backup_size_consistent(self):
        """Daily backup should not vary wildly from previous."""
        returncode, stdout, stderr = ssh_command(
            f'du -b {BACKUP_DIR}/daily/* | sort -k2 -r | head -2 | cut -f1'
        )

        if returncode == 0 and stdout.strip():
            sizes = [int(s) for s in stdout.strip().split('\n') if s]

            if len(sizes) >= 2:
                latest, previous = sizes[0], sizes[1]
                ratio = latest / previous if previous > 0 else 0

                # Size should be within 50% of previous
                assert 0.5 < ratio < 2.0, f"Backup size changed significantly: {ratio:.2f}x"


class TestDRScriptReady:
    """Tests for DR restore script availability."""

    @pytest.mark.slow
    def test_dr_restore_script_exists(self):
        """DR restore script should exist and be executable."""
        returncode, stdout, stderr = ssh_command(
            'test -x /var/www/nordabiznes/scripts/dr-restore.sh && echo "OK"'
        )

        assert returncode == 0, f"DR restore script not found or not executable: {stderr}"
        assert 'OK' in stdout


class TestBackupCronActive:
    """Tests for backup cron jobs."""

    @pytest.mark.slow
    def test_backup_cron_exists(self):
        """Backup cron job should be configured."""
        returncode, stdout, stderr = ssh_command(
            'cat /etc/cron.d/nordabiz-backup 2>/dev/null || crontab -l | grep nordabiz'
        )

        # Either cron.d file exists or user crontab has entry
        assert returncode == 0 or 'nordabiz' in stdout.lower(), "No backup cron found"
