"""Local account → browser-issued HTTP key → git push to an empty project."""

from __future__ import annotations

import json
import os
import subprocess
from pathlib import Path

import pytest

from integration.harness import running_server

sync_api = pytest.importorskip("playwright.sync_api")

_USERNAME = "alice"
_PASSWORD = "secretsecret"
_KEY_ID = "laptop"
_PROJECT = "emptyproj"


def _write_local_auth_config(path: Path) -> None:
    path.write_text(
        json.dumps(
            {
                "salt": "0123456789abcdef",
                "auth_mode": "local",
                "oauth_permissions": {
                    "*": [],
                    "pgw.read.*": ["*"],
                    "pgw.write.*": ["*"],
                },
                "local_users": [
                    {
                        "user": _USERNAME,
                        "pass": _PASSWORD,
                        "email": "alice@example.com",
                    }
                ],
            },
            indent=2,
        )
        + "\n",
        encoding="utf-8",
    )
    if os.name != "nt":
        path.chmod(0o600)


def _run_git(repo_dir: Path, *args: str, git_config: tuple[str, ...] = ()) -> str:
    completed = subprocess.run(
        ["git", *git_config, *args],
        cwd=repo_dir,
        capture_output=True,
        text=True,
        check=True,
        env={**os.environ, "GIT_TERMINAL_PROMPT": "0"},
    )
    return completed.stdout.strip()


def _key_git_config(username: str, secret: str) -> tuple[str, ...]:
    helper = f"!f() {{ echo username={username}; echo password={secret}; }}; f"
    return ("-c", "credential.helper=", "-c", f"credential.helper={helper}")


def _issue_key_via_browser(base: str) -> str:
    with sync_api.sync_playwright() as playwright:
        browser = playwright.chromium.launch(headless=True)
        try:
            page = browser.new_page()
            page.goto(f"{base}login?next=/user", wait_until="domcontentloaded")
            page.fill("#login_username", _USERNAME)
            page.fill("#login_password", _PASSWORD)
            page.get_by_role("button", name="Sign in").click()
            page.wait_for_url("**/user")
            sync_api.expect(page.get_by_role("heading", name="Account")).to_be_visible()
            page.fill("#api-key-id", _KEY_ID)
            page.get_by_role("button", name="Create key").click()
            page.locator("#api-key-secret-panel").wait_for(state="visible")
            secret = page.locator("#api-key-secret").input_value()
            assert secret, "expected a plaintext API key after Create key"
            return secret
        finally:
            browser.close()


@pytest.mark.playwright
def test_local_account_issues_key_and_pushes(tmp_path: Path) -> None:
    projects = tmp_path / "projects"
    projects.mkdir()
    bare = projects / _PROJECT
    subprocess.run(["git", "init", "--bare", "-b", "main", str(bare)], check=True, capture_output=True)

    auth_path = tmp_path / "auth.json"
    _write_local_auth_config(auth_path)

    with running_server(
        tmp_path=tmp_path,
        projects=projects,
        auth=True,
        auth_config_file=auth_path,
    ) as base:
        secret = _issue_key_via_browser(base)

        work = tmp_path / "work"
        work.mkdir()
        _run_git(work, "init", "-b", "main")
        _run_git(work, "config", "user.name", "tester")
        _run_git(work, "config", "user.email", "tester@example.com")
        (work / "README.md").write_text("from key\n", encoding="utf-8")
        _run_git(work, "add", "README.md")
        _run_git(work, "commit", "-m", "initial via http key")
        remote = f"{base}http/{_PROJECT}.git"
        _run_git(work, "remote", "add", "origin", remote)
        git_config = _key_git_config(_USERNAME, secret)
        _run_git(work, "push", "-u", "origin", "main", git_config=git_config)

        head = _run_git(bare, "rev-parse", "refs/heads/main")
        assert head
        subject = _run_git(bare, "log", "-1", "--format=%s", "refs/heads/main")
        assert subject == "initial via http key"