from __future__ import annotations

import os
import subprocess
from pathlib import Path


def _run_script_prefix(
    tmp_path: Path,
    relative_script_path: str,
    env_file_content: str,
    env: dict[str, str],
    output_vars: list[str],
) -> subprocess.CompletedProcess[str]:
    project_dir = tmp_path / "project"
    script_source = Path(__file__).resolve().parents[2] / relative_script_path
    script_copy = project_dir / relative_script_path
    script_copy.parent.mkdir(parents=True, exist_ok=True)
    script_copy.write_text(script_source.read_text(encoding="utf-8"), encoding="utf-8")
    (project_dir / ".env").write_text(env_file_content, encoding="utf-8")

    script_prefix = script_copy.read_text(encoding="utf-8").split('case "$MODE" in', 1)[0]
    print_lines = "\n".join(f'printf "{name}=%s\\n" "${{{name}:-}}"' for name in output_vars)
    command = f"""{script_prefix}
{print_lines}
"""

    return subprocess.run(
        ["bash", "-c", command, str(script_copy)],
        capture_output=True,
        text=True,
        env={**os.environ, **env, "MODE": "test"},
        cwd=script_copy.parent,
        check=False,
    )


def test_server_start_can_prefer_env_file_over_inherited_onlyoffice_values(tmp_path: Path) -> None:
    result = _run_script_prefix(
        tmp_path,
        "server/server_start.sh",
        env_file_content=(
            "ONLYOFFICE_ENABLED=true\n"
            "ONLYOFFICE_PUBLIC_URL=http://10.10.10.122:8082\n"
            "ONLYOFFICE_BACKEND_URL=http://main:8000\n"
            "ONLYOFFICE_JWT_SECRET=change-me-onlyoffice\n"
        ),
        env={
            "ONLYOFFICE_ENABLED": "false",
            "ONLYOFFICE_PUBLIC_URL": "http://127.0.0.1:8082",
            "X_FINANCIAL_PREFER_ENV_FILE": "true",
        },
        output_vars=["ONLYOFFICE_ENABLED", "ONLYOFFICE_PUBLIC_URL"],
    )

    assert result.returncode == 0, result.stderr
    assert "ONLYOFFICE_ENABLED=true" in result.stdout
    assert "ONLYOFFICE_PUBLIC_URL=http://10.10.10.122:8082" in result.stdout


def test_root_start_can_prefer_env_file_over_inherited_onlyoffice_values(tmp_path: Path) -> None:
    result = _run_script_prefix(
        tmp_path,
        "start.sh",
        env_file_content=(
            "ONLYOFFICE_ENABLED=true\n"
            "ONLYOFFICE_PUBLIC_URL=http://10.10.10.122:8082\n"
            "ONLYOFFICE_BACKEND_URL=http://main:8000\n"
            "ONLYOFFICE_JWT_SECRET=change-me-onlyoffice\n"
        ),
        env={
            "ONLYOFFICE_ENABLED": "false",
            "ONLYOFFICE_PUBLIC_URL": "http://127.0.0.1:8082",
            "X_FINANCIAL_PREFER_ENV_FILE": "true",
        },
        output_vars=["ONLYOFFICE_ENABLED", "ONLYOFFICE_PUBLIC_URL"],
    )

    assert result.returncode == 0, result.stderr
    assert "ONLYOFFICE_ENABLED=true" in result.stdout
    assert "ONLYOFFICE_PUBLIC_URL=http://10.10.10.122:8082" in result.stdout


def test_root_start_preserves_inherited_database_runtime_values(tmp_path: Path) -> None:
    result = _run_script_prefix(
        tmp_path,
        "start.sh",
        env_file_content=(
            "POSTGRES_HOST=external-db\n"
            "POSTGRES_PORT=6432\n"
            "POSTGRES_DB=external_financial\n"
            "POSTGRES_USER=external_user\n"
            "POSTGRES_PASSWORD=external_password\n"
            "DATABASE_URL=postgresql://external_user:external_password@external-db:6432/external_financial\n"
        ),
        env={
            "POSTGRES_HOST": "postgres",
            "POSTGRES_PORT": "5432",
            "POSTGRES_DB": "x_financial",
            "POSTGRES_USER": "x_financial",
            "POSTGRES_PASSWORD": "x_financial",
            "DATABASE_URL": "postgresql://x_financial:x_financial@postgres:5432/x_financial",
        },
        output_vars=[
            "POSTGRES_HOST",
            "POSTGRES_PORT",
            "POSTGRES_DB",
            "POSTGRES_USER",
            "POSTGRES_PASSWORD",
            "DATABASE_URL",
        ],
    )

    assert result.returncode == 0, result.stderr
    assert "POSTGRES_HOST=postgres" in result.stdout
    assert "POSTGRES_PORT=5432" in result.stdout
    assert "POSTGRES_DB=x_financial" in result.stdout
    assert "POSTGRES_USER=x_financial" in result.stdout
    assert "POSTGRES_PASSWORD=x_financial" in result.stdout
    expected_database_url = "postgresql://x_financial:x_financial@postgres:5432/x_financial"
    assert f"DATABASE_URL={expected_database_url}" in result.stdout


def test_web_start_preserves_inherited_runtime_ports(tmp_path: Path) -> None:
    result = _run_script_prefix(
        tmp_path,
        "web/web_start.sh",
        env_file_content=(
            "WEB_HOST=10.10.10.122\n"
            "WEB_PORT=5273\n"
            "SERVER_HOST=10.10.10.122\n"
            "SERVER_PORT=9000\n"
            "POSTGRES_HOST=10.10.10.189\n"
        ),
        env={
            "WEB_HOST": "0.0.0.0",
            "WEB_PORT": "5173",
            "SERVER_HOST": "0.0.0.0",
            "SERVER_PORT": "8000",
            "POSTGRES_HOST": "www.caoxiaozhu.com",
        },
        output_vars=["WEB_HOST", "WEB_PORT", "SERVER_HOST", "SERVER_PORT", "POSTGRES_HOST"],
    )

    assert result.returncode == 0, result.stderr
    assert "WEB_HOST=0.0.0.0" in result.stdout
    assert "WEB_PORT=5173" in result.stdout
    assert "SERVER_HOST=0.0.0.0" in result.stdout
    assert "SERVER_PORT=8000" in result.stdout
    assert "POSTGRES_HOST=www.caoxiaozhu.com" in result.stdout


def test_server_start_preserves_inherited_runtime_guards(tmp_path: Path) -> None:
    result = _run_script_prefix(
        tmp_path,
        "server/server_start.sh",
        env_file_content=(
            "SERVER_HOST=10.10.10.122\n"
            "SERVER_PORT=9000\n"
            "STARTUP_BOOTSTRAP_ENABLED=true\n"
            "BACKGROUND_SCHEDULERS_ENABLED=true\n"
        ),
        env={
            "SERVER_HOST": "0.0.0.0",
            "SERVER_PORT": "8000",
            "STARTUP_BOOTSTRAP_ENABLED": "false",
            "BACKGROUND_SCHEDULERS_ENABLED": "false",
        },
        output_vars=[
            "SERVER_HOST",
            "SERVER_PORT",
            "STARTUP_BOOTSTRAP_ENABLED",
            "BACKGROUND_SCHEDULERS_ENABLED",
        ],
    )

    assert result.returncode == 0, result.stderr
    assert "SERVER_HOST=0.0.0.0" in result.stdout
    assert "SERVER_PORT=8000" in result.stdout
    assert "STARTUP_BOOTSTRAP_ENABLED=false" in result.stdout
    assert "BACKGROUND_SCHEDULERS_ENABLED=false" in result.stdout


def test_server_start_preserves_inherited_database_runtime_values(tmp_path: Path) -> None:
    result = _run_script_prefix(
        tmp_path,
        "server/server_start.sh",
        env_file_content=(
            "POSTGRES_HOST=external-db\n"
            "POSTGRES_PORT=6432\n"
            "POSTGRES_DB=external_financial\n"
            "POSTGRES_USER=external_user\n"
            "POSTGRES_PASSWORD=external_password\n"
            "DATABASE_URL=postgresql://external_user:external_password@external-db:6432/external_financial\n"
        ),
        env={
            "POSTGRES_HOST": "postgres",
            "POSTGRES_PORT": "5432",
            "POSTGRES_DB": "x_financial",
            "POSTGRES_USER": "x_financial",
            "POSTGRES_PASSWORD": "x_financial",
            "DATABASE_URL": "postgresql://x_financial:x_financial@postgres:5432/x_financial",
        },
        output_vars=[
            "POSTGRES_HOST",
            "POSTGRES_PORT",
            "POSTGRES_DB",
            "POSTGRES_USER",
            "POSTGRES_PASSWORD",
            "DATABASE_URL",
        ],
    )

    assert result.returncode == 0, result.stderr
    assert "POSTGRES_HOST=postgres" in result.stdout
    assert "POSTGRES_PORT=5432" in result.stdout
    assert "POSTGRES_DB=x_financial" in result.stdout
    assert "POSTGRES_USER=x_financial" in result.stdout
    assert "POSTGRES_PASSWORD=x_financial" in result.stdout
    expected_database_url = "postgresql://x_financial:x_financial@postgres:5432/x_financial"
    assert f"DATABASE_URL={expected_database_url}" in result.stdout


def test_default_compose_isolates_local_postgres_from_external_env_values() -> None:
    compose = (Path(__file__).resolve().parents[2] / "docker-compose.yml").read_text(
        encoding="utf-8"
    )

    assert "condition: service_healthy" in compose
    assert "container_name: x-financial-local-postgres" in compose
    assert "${LOCAL_POSTGRES_DB:-x_financial}" in compose
    assert "${LOCAL_POSTGRES_USER:-x_financial}" in compose
    assert "${LOCAL_POSTGRES_PASSWORD:-x_financial}" in compose
    assert "${LOCAL_POSTGRES_HOST_PORT:-55432}" in compose
    assert "${POSTGRES_DB:-x_financial}" not in compose
    assert "${POSTGRES_USER:-x_financial}" not in compose
    assert "${POSTGRES_PASSWORD:-x_financial}" not in compose
