#include "../administrator.hpp"

auto administrator::operator()(administration::get_idp_user_info &&v, administration::engine::session &session)
{
	auto &&[login, idp_name, parameters] = std::move(v).tuple();

	auto idp = authenticator_.get_identity_provider(idp_name);

	if (!idp) {
		logger_.log_u(fz::logmsg::error, L"administration::get_idp_user_info failed. Reason: IDP '%s' is not registered. This is an internal error.", idp_name);
		session.send(v.failure());
		return;
	}

	server_context_.pool().spawn([sa = shared_self_, id = session.get_id(), idp, login = std::move(login), parameters = std::move(parameters)]() mutable {
		auto a = sa.lock();
		if (!a) {
			return;
		}

		if (!a->admin_server_.get_session(id)) {
			return;
		}

		fz::authentication::identity_provider::user_info uinfo;
		auto error = idp->get_user_info(login, parameters, uinfo);
		if (error) {
			a->logger_.log_u(fz::logmsg::error, L"administration::get_idp_user_info failed. Reason: %s.", error);
		}

		if (auto s = a->admin_server_.get_session(id)) {
			if (error) {
				s->send<administration::get_idp_user_info::response>(administration::get_idp_user_info::failure(error));
				return;
			}

			s->send<administration::get_idp_user_info::response>(administration::get_idp_user_info::success(std::move(uinfo)));
		}
	}).detach();
}

auto administrator::operator()(administration::get_idp_properties &&v, administration::engine::session &session)
{
	auto &&[idp_name, parameters] = std::move(v).tuple();

	auto idp = authenticator_.get_identity_provider(idp_name);

	if (!idp) {
		logger_.log_u(fz::logmsg::error, L"administration::get_idp_user_info failed. Reason: IDP '%s' is not registered. This is an internal error.", idp_name);
		session.send(v.failure());
		return;
	}

	server_context_.pool().spawn([sa = shared_self_, id = session.get_id(), idp, parameters = std::move(parameters)]() mutable {
		auto a = sa.lock();
		if (!a) {
			return;
		}

		if (!a->admin_server_.get_session(id)) {
			return;
		}

		auto properties = idp->get_properties(parameters);
		if (!properties) {
			a->logger_.log_u(fz::logmsg::error, L"administration::get_idp_user_info failed.");
		}

		if (auto s = a->admin_server_.get_session(id)) {
			if (!properties) {
				s->send<administration::get_idp_user_info::response>(administration::get_idp_user_info::failure());
				return;
			}

			s->send<administration::get_idp_properties::response>(administration::get_idp_properties::success(std::move(*properties)));
		}
	}).detach();
}

FZ_RMP_INSTANTIATE_HERE_DISPATCHING_FOR(administration::engine, administrator, administration::get_idp_user_info);
FZ_RMP_INSTANTIATE_HERE_DISPATCHING_FOR(administration::engine, administrator, administration::get_idp_properties);
