package no.valg.valgnatt.backend.rapport;

import com.google.gson.JsonArray;
import no.valg.valgnatt.backend.MainBackend;
import no.valg.valgnatt.common.ValgnattException;
import no.valg.valgnatt.database.GrunnlagsdataCache;
import no.valg.valgnatt.database.Konstanter;
import no.valg.valgnatt.database.domene.ValgType;
import org.springframework.jdbc.datasource.DataSourceUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;

class UtjevningsmandatRapport {

	private UtjevningsmandatRapport() {
	}

	static String lagRapport(DataSource dataSource, GrunnlagsdataCache grunnlagsdataCache, MainRapport main) {


		JsonObjectWrapper rapp = new JsonObjectWrapper();
		leggTilTidspunkt(rapp);
		JsonObjectWrapper utjevningsmandatKvotienter = rapp.leggTilObjekt("utjevningmandatKvotienter");
		JsonArray resultatTabell = utjevningsmandatKvotienter.leggTilTabell("resultat");
		leggTilUjmKvotienterForResultatEllerPrognose(dataSource, grunnlagsdataCache, resultatTabell, false);
		
		boolean prognosemodus = main.getMainBackend().getFaktiskBeregningsmetode() == MainBackend.Beregningsmetode.PROGNOSE;
		if (prognosemodus) {
			JsonArray prognoseTabell = utjevningsmandatKvotienter.leggTilTabell("prognose");
			leggTilUjmKvotienterForResultatEllerPrognose(dataSource, grunnlagsdataCache, prognoseTabell, true);
		} 
		
		return rapp.getJsonObject().toString();
	}

	private static void leggTilUjmKvotienterForResultatEllerPrognose(DataSource dataSource, GrunnlagsdataCache grunnlagsdataCache, JsonArray tabell, boolean prognose) {
		if (grunnlagsdataCache.hasValgType(ValgType.ST)) {
            leggTilUtjevningsmandatKvotienter(dataSource, tabell, ValgType.ST, prognose);
        } else if (grunnlagsdataCache.hasValgType(ValgType.FY)) {
            // Selv om valgtype er FY, så gjelder utregningene for et slags ST-skygge-valg
            leggTilUtjevningsmandatKvotienter(dataSource, tabell, ValgType.FY, prognose);
        }
	}

	private static void leggTilUtjevningsmandatKvotienter(DataSource dataSource, JsonArray utjevningsmandatKvotienter, ValgType vt, boolean prognose) {
		Connection con = null;
		try {
			con = DataSourceUtils.getConnection(dataSource);
			String sql = "SELECT partikode, substr(valgdistriktnr, 1, 2) fylke, restkvotient_utj, mandatrang_utj\n" +
					"FROM mandatberegning \n" +
					"WHERE valgtype= '" + vt.name() + "' \n" +
					"      AND valgdistriktnr != '" + Konstanter.VALGDISTRIKT_NORGE + "' \n" +
					"      AND restkvotient_utj != 0\n" +
					"      AND prognose = '" + (prognose ? "1" : "0") + "'\n" +
					"ORDER BY restkvotient_utj DESC, partikode ASC";
			try (PreparedStatement ps = con.prepareStatement(sql); ResultSet rset = ps.executeQuery()) {
				while (rset.next()) {
					JsonObjectWrapper utjevningsmandatKvotient = new JsonObjectWrapper();
					utjevningsmandatKvotienter.add(utjevningsmandatKvotient.getJsonObject());
					utjevningsmandatKvotient.leggTilString("partikode", rset.getString("partikode"));
					utjevningsmandatKvotient.leggTilString("fylkeNr", rset.getString("fylke"));
					utjevningsmandatKvotient.leggTilTall("mandatrang", rset.getString("mandatrang_utj"));
					utjevningsmandatKvotient.leggTilTall("veietRestkvotient", Format.kvotient(rset.getDouble("restkvotient_utj")));
				}
			}
		} catch (SQLException sqle) {
			throw new ValgnattException(sqle);
		} finally {
			DataSourceUtils.releaseConnection(con, dataSource);
		}
	}

	private static void leggTilTidspunkt(JsonObjectWrapper rapp) {
		JsonObjectWrapper tidspunkt = rapp.leggTilObjekt("tidspunkt");
		tidspunkt.leggTilString("rapportGenerert", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(new Date()));
	}
}
