#!/usr/bin/python3

import os
import pathlib
import tempfile

import pytest

from osbuild.testutil import has_executable
from osbuild.testutil.net import http_serve_directory, https_serve_directory
from osbuild.util import ostree

SOURCES_NAME = "org.osbuild.ostree"


@pytest.mark.skipif(not has_executable("ostree"), reason="need ostree")
def test_ostree_source_not_exists(tmp_path, sources_service):
    checksum = "sha256:1111111111111111111111111111111111111111111111111111111111111111"
    sources_service.setup({"cache": tmp_path, "options": {}})
    assert not sources_service.exists(checksum, None)


@pytest.mark.skipif(not has_executable("ostree"), reason="need ostree")
def test_ostree_source_exists(tmp_path, sources_service):
    sources_service.setup({"cache": tmp_path, "options": {}})
    root = tmp_path / "org.osbuild.ostree" / "repo"
    commit = make_repo(root)
    assert sources_service.exists("sha256:" + commit, None)


def make_test_sources(proto, port, fake_commit, **secrets):
    sources = {
        fake_commit: {
            "remote": {
                "url": f"{proto}://localhost:{port}",
            }
        }
    }
    if secrets:
        sources[fake_commit]["remote"]["secrets"] = secrets
    return sources


def make_repo(root):
    with tempfile.TemporaryDirectory() as empty_tmpdir:
        ostree.cli("init", f"--repo={root}")
        return ostree.cli("commit", f"--repo={root}", "--orphan", empty_tmpdir).stdout.rstrip()


@pytest.mark.skipif(not has_executable("ostree"), reason="need ostree")
def test_ostree_pull_plain(tmp_path, sources_service):
    fake_httpd_root = tmp_path / "fake-httpd-root"
    fake_httpd_root.mkdir(exist_ok=True)
    fake_commit = make_repo(fake_httpd_root)

    with http_serve_directory(fake_httpd_root) as httpd:
        test_sources = make_test_sources("http", httpd.server_port, fake_commit)
        sources_service.setup({"cache": tmp_path, "options": {}})
        sources_service.fetch_all(test_sources)
        assert sources_service.exists("sha256:" + fake_commit, None)


@pytest.mark.skipif(not has_executable("ostree"), reason="need ostree")
def test_ostree_pull_plain_mtls(tmp_path, sources_service, monkeypatch):
    fake_httpd_root = tmp_path / "fake-httpd-root"
    fake_httpd_root.mkdir(exist_ok=True)
    fake_commit = make_repo(fake_httpd_root)

    cert_dir = pathlib.Path(__file__).parent.parent.parent / "test" / "data" / "certs"
    cert1 = cert_dir / "cert1.pem"
    assert cert1.exists()
    key1 = cert_dir / "key1.pem"
    assert key1.exists()

    with https_serve_directory(fake_httpd_root, cert1, key1) as httpd:
        monkeypatch.setenv("OSBUILD_SOURCES_OSTREE_INSECURE", "1")
        test_sources = make_test_sources("https", httpd.server_port, fake_commit, name="org.osbuild.mtls")
        sources_service.setup({"cache": tmp_path, "options": {}})
        sources_service.fetch_all(test_sources)
        assert sources_service.exists("sha256:" + fake_commit, None)


@pytest.mark.skipif(not has_executable("ostree"), reason="need ostree")
def test_ostree_copy_all(tmp_path, sources_service):
    fake_httpd_root = tmp_path / "fake-httpd-root"
    fake_httpd_root.mkdir(exist_ok=True)
    fake_commit = make_repo(fake_httpd_root)
    src_cache = tmp_path / "src-cache"
    dst_cache = tmp_path / "dst-cache"

    os.mkdir(src_cache)
    os.mkdir(dst_cache)

    with http_serve_directory(fake_httpd_root) as httpd:
        test_sources = make_test_sources("http", httpd.server_port, fake_commit)
        sources_service.setup({"cache": src_cache, "options": {}})
        sources_service.fetch_all(test_sources)
        sources_service.copy_all(test_sources, dst_cache)
        assert sources_service.exists("sha256:" + fake_commit, None)
        # ensure the commit exists in the dst_cache repo
        ostree.show(dst_cache / sources_service.content_type / "repo", "sha256:" + fake_commit)
