import importlib
import sys
import warnings
import pytest
import shutil
from hayhooks.server.app import create_app
from hayhooks.settings import AppSettings, check_cors_settings


@pytest.fixture
def temp_dir(tmp_path):
    yield tmp_path

    if tmp_path.exists():
        shutil.rmtree(tmp_path)


def test_custom_pipelines_dir(temp_dir):
    custom_dir = temp_dir / "custom_pipelines"
    settings = AppSettings(pipelines_dir=str(custom_dir))
    assert settings.pipelines_dir == str(custom_dir)


def test_root_path():
    settings = AppSettings(root_path="test_root")
    assert settings.root_path == "test_root"


def test_host():
    settings = AppSettings(host="test_host")
    assert settings.host == "test_host"


def test_port():
    settings = AppSettings(port=1234)
    assert settings.port == 1234


def test_env_var_prefix(monkeypatch):
    monkeypatch.setenv("HAYHOOKS_PORT", "5678")
    settings = AppSettings()
    assert settings.port == 5678


def test_cors():
    default_settings = AppSettings()
    assert default_settings.cors_allow_origins == ["*"]
    assert default_settings.cors_allow_methods == ["*"]
    assert default_settings.cors_allow_headers == ["*"]
    assert default_settings.cors_allow_credentials is False
    assert default_settings.cors_allow_origin_regex is None
    assert default_settings.cors_expose_headers == []
    assert default_settings.cors_max_age == 600

    custom_settings = AppSettings(
        cors_allow_origins=["https://example.com", "https://test.com"],
        cors_allow_methods=["GET", "POST"],
        cors_allow_headers=["X-Custom-Header"],
        cors_allow_credentials=True,
        cors_allow_origin_regex="https://.*\\.example\\.com",
        cors_expose_headers=["X-Custom-Expose"],
        cors_max_age=3600,
    )
    assert custom_settings.cors_allow_origins == ["https://example.com", "https://test.com"]
    assert custom_settings.cors_allow_methods == ["GET", "POST"]
    assert custom_settings.cors_allow_headers == ["X-Custom-Header"]
    assert custom_settings.cors_allow_credentials is True
    assert custom_settings.cors_allow_origin_regex == "https://.*\\.example\\.com"
    assert custom_settings.cors_expose_headers == ["X-Custom-Expose"]
    assert custom_settings.cors_max_age == 3600


def test_cors_env_vars(monkeypatch):
    monkeypatch.setenv("HAYHOOKS_CORS_ALLOW_ORIGINS", '["https://example.com"]')
    monkeypatch.setenv("HAYHOOKS_CORS_ALLOW_METHODS", '["GET", "POST"]')
    monkeypatch.setenv("HAYHOOKS_CORS_ALLOW_HEADERS", '["X-Test-Header"]')
    monkeypatch.setenv("HAYHOOKS_CORS_ALLOW_CREDENTIALS", "true")
    monkeypatch.setenv("HAYHOOKS_CORS_ALLOW_ORIGIN_REGEX", "https://.*\\.test\\.com")
    monkeypatch.setenv("HAYHOOKS_CORS_EXPOSE_HEADERS", '["X-Expose-Test"]')
    monkeypatch.setenv("HAYHOOKS_CORS_MAX_AGE", "1800")

    settings = AppSettings()
    assert settings.cors_allow_origins == ["https://example.com"]
    assert settings.cors_allow_methods == ["GET", "POST"]
    assert settings.cors_allow_headers == ["X-Test-Header"]
    assert settings.cors_allow_credentials is True
    assert settings.cors_allow_origin_regex == "https://.*\\.test\\.com"
    assert settings.cors_expose_headers == ["X-Expose-Test"]
    assert settings.cors_max_age == 1800


def test_cors_warning():
    with pytest.warns(
        UserWarning, match="Using default CORS settings - All origins, methods, and headers are allowed."
    ):
        check_cors_settings()

    with warnings.catch_warnings(record=True) as recorded_warnings:
        warnings.simplefilter("always")
        AppSettings(
            cors_allow_origins=["https://example.com"],
            cors_allow_methods=["GET", "POST"],
            cors_allow_headers=["X-Custom-Header"],
        )
        assert len(recorded_warnings) == 0


def test_additional_python_path():
    custom_path = "/custom/python/path"
    settings = AppSettings(additional_python_path=custom_path)
    assert settings.additional_python_path == custom_path


def test_additional_python_path_env_var(monkeypatch):
    custom_path = "/env/var/path"
    monkeypatch.setenv("HAYHOOKS_ADDITIONAL_PYTHON_PATH", custom_path)
    settings = AppSettings()
    assert settings.additional_python_path == custom_path


def test_additional_python_path_in_sys_path(monkeypatch, test_settings):

    original_sys_path = sys.path.copy()

    try:
        # Add a test path directly to the settings object
        test_path = "/test/python/path"
        test_settings.additional_python_path = test_path

        # Create the app which should add the path to sys.path
        # And verify the path was added
        create_app()
        assert test_path in sys.path

    finally:
        # Restore original sys.path
        sys.path = original_sys_path


def test_additional_python_path_in_sys_path_via_env(monkeypatch, test_settings):
    original_sys_path = sys.path.copy()

    try:
        # Set a test path via environment variable
        test_path = "/test/python/path"
        monkeypatch.setenv("HAYHOOKS_ADDITIONAL_PYTHON_PATH", test_path)

        # Reimport create_app after monkeypatch.setenv
        from hayhooks.server.app import create_app

        # Create the app which should add the path to sys.path
        # And verify the path was added
        create_app()
        assert test_path in sys.path

    finally:
        # Restore original sys.path
        sys.path = original_sys_path
