import sys
from pathlib import Path

# Add src to python path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))

from actions.sftp import handle_sftp_create, handle_sftp_delete, handle_sftp_reset_password
import pytest
from unittest.mock import MagicMock, patch, call


def test_sftp_create_success():
    payload = {
        "username_suffix": "mysite",
        "password": "secret_password",
        "home_directory": "/var/www/mysite"
    }
    
    # Mock user_exists to return False (so user is not duplicate)
    with patch("actions.sftp.user_exists", return_value=False) as mock_exists, \
         patch("subprocess.run") as mock_run:
        
        mock_sub = MagicMock()
        mock_sub.returncode = 0
        mock_run.return_value = mock_sub
        
        res = handle_sftp_create(payload)
        
        assert res["success"] is True
        assert res["username"] == "wolf_sftp_mysite"
        
        mock_exists.assert_called_once_with("wolf_sftp_mysite")
        
        # Verify subprocess calls
        # 1. useradd
        # 2. chpasswd
        # 3. chmod
        # 4. chown
        assert mock_run.call_count == 4
        
        calls = [
            call(["useradd", "-m", "-d", "/var/www/mysite", "-s", "/usr/sbin/nologin", "-g", "www-data", "wolf_sftp_mysite"], capture_output=True, text=True, check=False),
            call(["chpasswd"], input="wolf_sftp_mysite:secret_password", capture_output=True, text=True, check=False),
            call(["chmod", "750", "/var/www/mysite"], capture_output=True, text=True, check=False),
            call(["chown", "wolf_sftp_mysite:www-data", "/var/www/mysite"], capture_output=True, text=True, check=False)
        ]
        mock_run.assert_has_calls(calls)


def test_sftp_create_sanitized_suffix():
    payload = {
        "username_suffix": "my-site!_123$",
        "password": "secret_password",
        "home_directory": "/var/www/mysite"
    }
    
    # "my-site!_123$" -> alphanumeric + underscores -> "mysite_123"
    with patch("actions.sftp.user_exists", return_value=False), \
         patch("subprocess.run") as mock_run:
        
        mock_sub = MagicMock()
        mock_sub.returncode = 0
        mock_run.return_value = mock_sub
        
        res = handle_sftp_create(payload)
        
        assert res["success"] is True
        assert res["username"] == "wolf_sftp_mysite_123"


def test_sftp_create_invalid_suffix():
    payload = {
        "username_suffix": "!!!", # no alphanumeric/underscores -> empty
        "password": "secret_password",
        "home_directory": "/var/www/mysite"
    }
    
    with patch("actions.sftp.user_exists", return_value=False):
        res = handle_sftp_create(payload)
        assert res["success"] is False
        assert "Invalid or empty" in res["error"]


def test_sftp_create_duplicate_user():
    payload = {
        "username_suffix": "mysite",
        "password": "secret_password",
        "home_directory": "/var/www/mysite"
    }
    
    # Mock user_exists to return True
    with patch("actions.sftp.user_exists", return_value=True):
        res = handle_sftp_create(payload)
        assert res["success"] is False
        assert "already exists" in res["error"]


def test_sftp_delete_success():
    payload = {
        "username": "wolf_sftp_mysite"
    }
    
    with patch("actions.sftp.user_exists", return_value=True) as mock_exists, \
         patch("subprocess.run") as mock_run:
        
        mock_sub = MagicMock()
        mock_sub.returncode = 0
        mock_run.return_value = mock_sub
        
        res = handle_sftp_delete(payload)
        
        assert res["success"] is True
        assert res["username"] == "wolf_sftp_mysite"
        mock_exists.assert_called_once_with("wolf_sftp_mysite")
        
        mock_run.assert_called_once_with(["userdel", "-r", "wolf_sftp_mysite"], capture_output=True, text=True, check=False)


def test_sftp_delete_invalid_prefix():
    payload = {
        "username": "other_user"
    }
    
    res = handle_sftp_delete(payload)
    assert res["success"] is False
    assert "must start with" in res["error"]


def test_sftp_delete_nonexistent():
    payload = {
        "username": "wolf_sftp_nonexistent"
    }
    
    with patch("actions.sftp.user_exists", return_value=False):
        res = handle_sftp_delete(payload)
        assert res["success"] is False
        assert "does not exist" in res["error"]


def test_sftp_reset_password_success():
    payload = {
        "username": "wolf_sftp_mysite",
        "new_password": "new_secret_password"
    }
    
    with patch("actions.sftp.user_exists", return_value=True) as mock_exists, \
         patch("subprocess.run") as mock_run:
        
        mock_sub = MagicMock()
        mock_sub.returncode = 0
        mock_run.return_value = mock_sub
        
        res = handle_sftp_reset_password(payload)
        
        assert res["success"] is True
        assert res["username"] == "wolf_sftp_mysite"
        mock_exists.assert_called_once_with("wolf_sftp_mysite")
        
        mock_run.assert_called_once_with(["chpasswd"], input="wolf_sftp_mysite:new_secret_password", capture_output=True, text=True, check=False)


def test_sftp_reset_password_invalid_prefix():
    payload = {
        "username": "other_user",
        "new_password": "new_secret_password"
    }
    
    res = handle_sftp_reset_password(payload)
    assert res["success"] is False
    assert "must start with" in res["error"]
