from test/more import *;

requires_capability( "fs" );

from std/data/json import JSON;
from std/io import Path;
from std/zuzuzoo import Zuzuzoo, can_upgrade;

class FakeRequest {
	let req_method := "";
	let req_url := "";
}

class FakeResponse {
	let payload := null;
	let response_url := "";

	method expect_success () {
		return self;
	}

	method json () {
		return payload;
	}

	method url () {
		return response_url;
	}
}

class FakeUserAgent {
	let response := null;

	method build_request ( verb, url ) {
		return new FakeRequest( req_method: verb, req_url: url );
	}

	method send ( request ) {
		return response;
	}
}

function ensure_dir ( path ) {
	return true if path.exists();
	let parent := path.parent();
	ensure_dir(parent) if not parent.exists();
	path.mkdir();
	return true;
}

function root () {
	let dir := Path.tempdir();
	let lib := dir.child("lib");
	let bin := dir.child("bin");
	let meta := dir.child("meta");
	ensure_dir(lib);
	ensure_dir(bin);
	ensure_dir(meta);
	return {
		dir_obj: dir,
		lib_obj: lib,
		bin_obj: bin,
		meta_obj: meta,
		lib_dir: lib.to_String(),
		bin_dir: bin.to_String(),
		meta_dir: meta.to_String(),
	};
}

function write_installed ( root, name, version, module_name ) {
	( new JSON( pretty: true ) ).dump(
		root{meta_obj}.child( name _ "-" _ version _ ".json" ),
		{
			name: name,
			version: version,
			author: "Example",
			license: "MIT",
			status: "stable",
			dependencies: {},
			installed: {
				zdf: "ZDF-1",
				lib_dir: root{lib_dir},
				bin_dir: root{bin_dir},
				meta_dir: root{meta_dir},
				modules: [
					{
						source: "modules/" _ module_name _ ".zzm",
						install_as: module_name _ ".zzm",
						sha256: "abc",
					},
				],
				scripts: [],
			},
		},
	);
}

let target := root();
write_installed( target, "upgrade-app", "1.0.0", "upgrade/app" );
let ua := new FakeUserAgent(
	response: new FakeResponse(
		response_url: "https://packages.example/module/upgrade/app.json",
		payload: {
			name: "upgrade-app",
			version: "2.0.0",
			author: "Example",
			license: "MIT",
			status: "stable",
		},
	),
);
let opts := {
	lib_dir: target{lib_dir},
	bin_dir: target{bin_dir},
	meta_dir: target{meta_dir},
	home: Path.tempdir().to_String(),
	base_url: "https://packages.example",
	user_agent: ua,
};

let zoo := new Zuzuzoo(
	lib_dir: opts{lib_dir},
	bin_dir: opts{bin_dir},
	meta_dir: opts{meta_dir},
	home: opts{home},
	base_url: opts{base_url},
	user_agent: ua,
);
let latest_result := zoo.latest("upgrade/app");

is( latest_result{status}, "outdated", "latest reports outdated" );
is( latest_result{installed_version}, "1.0.0", "installed version is reported" );
is( latest_result{remote_version}, "2.0.0", "remote version is reported" );
is( latest_result{can_upgrade}, true, "outdated can be upgraded" );

let upgrade_result := can_upgrade( "upgrade/app", opts );
is( upgrade_result{status}, "outdated", "can_upgrade delegates to latest" );
is( upgrade_result{can_upgrade}, true, "can_upgrade keeps structured flag" );

done_testing();
