/*
 * Copyright 2021-2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.opentest4j.reporting.tooling.core.htmlreport;

import org.apiguardian.api.API;
import org.joox.Match;
import org.opentest4j.reporting.events.git.Branch;
import org.opentest4j.reporting.events.git.Commit;
import org.opentest4j.reporting.events.git.Repository;
import org.opentest4j.reporting.events.git.Status;
import org.opentest4j.reporting.tooling.spi.htmlreport.Block;
import org.opentest4j.reporting.tooling.spi.htmlreport.Contributor;
import org.opentest4j.reporting.tooling.spi.htmlreport.KeyValuePairs;
import org.opentest4j.reporting.tooling.spi.htmlreport.PreFormattedOutput;
import org.opentest4j.reporting.tooling.spi.htmlreport.Section;
import org.opentest4j.reporting.tooling.spi.htmlreport.Subsections;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.apiguardian.api.API.Status.INTERNAL;
import static org.joox.JOOX.$;
import static org.opentest4j.reporting.tooling.core.htmlreport.CoreContributor.addToTable;
import static org.opentest4j.reporting.tooling.core.htmlreport.CoreContributor.findChild;

/**
 * Contributes sections to the HTML report elements in the git schema.
 *
 * @since 0.2.0
 */
@API(status = INTERNAL, since = "0.2.0")
public class GitContributor implements Contributor {

	/**
	 * Create a new instance.
	 */
	public GitContributor() {
	}

	@Override
	public List<Section> contributeSectionsForExecution(Context context) {
		var sections = new ArrayList<Section>();
		var infrastructure = $(context.element()).child("infrastructure");
		createGitSection(infrastructure).ifPresent(sections::add);
		return sections;
	}

	private static Optional<Section> createGitSection(Match infrastructure) {

		var table = KeyValuePairs.builder();
		Block<?> statusBlock = null;

		var originUrl = findChild(infrastructure, Repository.ELEMENT).attr("originUrl");
		if (originUrl != null) {
			table.putContent("Origin", originUrl);
		}

		addToTable(infrastructure, Branch.ELEMENT, "Branch", table::putContent);
		addToTable(infrastructure, Commit.ELEMENT, "Commit hash", table::putContent);

		var status = findChild(infrastructure, Status.ELEMENT);
		if (status.isNotEmpty()) {
			table.putContent("Clean", status.attr("clean"));
			if (!status.text().isBlank()) {
				var codeBlock = PreFormattedOutput.builder().content(status.text()).build();
				var subsection = Section.builder().title("Status of working tree").addBlock(codeBlock).build();
				statusBlock = Subsections.builder().addContent(subsection).build();
			}
		}

		var sectionBuilder = Section.builder().title("Git").order(15);

		var keyValuePairs = table.build();
		if (!keyValuePairs.getContent().isEmpty()) {
			sectionBuilder.addBlock(keyValuePairs);
		}

		if (statusBlock != null) {
			sectionBuilder.addBlock(statusBlock);
		}

		var section = sectionBuilder.build();

		return section.getBlocks().isEmpty() ? Optional.empty() : Optional.of(section);
	}
}
