package de.avatic.lcc.controller.calculation;

import de.avatic.lcc.model.db.nodes.Location;
import de.avatic.lcc.model.db.premises.Premise;
import de.avatic.lcc.model.db.premises.PremiseState;
import de.avatic.lcc.model.db.premises.route.Destination;
import de.avatic.lcc.model.db.premises.route.Route;
import de.avatic.lcc.model.db.utils.DimensionUnit;
import de.avatic.lcc.model.db.utils.WeightUnit;
import org.springframework.boot.test.context.TestComponent;
import org.springframework.jdbc.core.JdbcTemplate;

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

@TestComponent
public class PremiseTestsHelper {

    private final JdbcTemplate jdbcTemplate;

    public PremiseTestsHelper(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public List<Premise> getPremisesFromDb() {
        String query = "SELECT * FROM premise";
        return jdbcTemplate.query(query, (rs, rowNum) -> {
            var entity = new Premise();

            entity.setId(rs.getInt("id"));

            entity.setPackagingId(rs.getInt("packaging_id"));
            if (rs.wasNull())
                entity.setPackagingId(null);

            entity.setMaterialId(rs.getInt("material_id"));
            if (rs.wasNull())
                entity.setMaterialId(null);

            entity.setSupplierNodeId(rs.getInt("supplier_node_id"));
            if (rs.wasNull())
                entity.setSupplierNodeId(null);

            entity.setUserSupplierNodeId(rs.getInt("user_supplier_node_id"));
            if (rs.wasNull())
                entity.setUserSupplierNodeId(null);

            entity.setLocation(new Location(rs.getBigDecimal("geo_lng").doubleValue(), rs.getBigDecimal("geo_lat").doubleValue()));

            entity.setCountryId(rs.getInt("country_id"));
            if (rs.wasNull())
                entity.setCountryId(null);

            entity.setUserId(rs.getInt("user_id"));
            if (rs.wasNull())
                entity.setUserId(null);

            entity.setMaterialCost(rs.getBigDecimal("material_cost"));

            entity.setHsCode(rs.getString("hs_code"));

            entity.setTariffRate(rs.getBigDecimal("tariff_rate"));

            entity.setFcaEnabled(rs.getBoolean("is_fca_enabled"));
            if (rs.wasNull())
                entity.setFcaEnabled(null);

            entity.setOverseaShare(rs.getBigDecimal("oversea_share"));

            entity.setIndividualHuHeight(rs.getInt("individual_hu_height"));
            if (rs.wasNull())
                entity.setIndividualHuHeight(null);

            entity.setIndividualHuWidth(rs.getInt("individual_hu_width"));
            if (rs.wasNull())
                entity.setIndividualHuWidth(null);

            entity.setIndividualHuLength(rs.getInt("individual_hu_length"));
            if (rs.wasNull())
                entity.setIndividualHuLength(null);

            entity.setIndividualHuWeight(rs.getInt("individual_hu_weight"));
            if (rs.wasNull())
                entity.setIndividualHuWeight(null);

            entity.setHuDisplayedDimensionUnit(DimensionUnit.valueOf(rs.getString("hu_displayed_dimension_unit")));
            entity.setHuDisplayedWeightUnit(WeightUnit.valueOf(rs.getString("hu_displayed_weight_unit")));

            entity.setHuStackable(rs.getBoolean("hu_stackable"));
            if (rs.wasNull())
                entity.setHuStackable(null);

            entity.setHuMixable(rs.getBoolean("hu_mixable"));
            if (rs.wasNull())
                entity.setHuMixable(null);

            entity.setHuUnitCount(rs.getInt("hu_unit_count"));
            if (rs.wasNull())
                entity.setHuUnitCount(null);

            entity.setState(PremiseState.valueOf(rs.getString("state")));
            entity.setUpdatedAt(rs.getTimestamp("updated_at").toLocalDateTime());
            entity.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());

            return entity;
        });
    }

    public Integer getNodeIdByExternalMappingId(String mappingId) {
        String query = "SELECT id FROM node WHERE external_mapping_id = ? LIMIT 1";
        return jdbcTemplate.queryForObject(query, Integer.class, mappingId);
    }

    public Integer getUserNodeIdByName(String name) {
        String query = "SELECT id FROM sys_user_node WHERE name = ? LIMIT 1";
        return jdbcTemplate.queryForObject(query, Integer.class, name);
    }

    public List<Integer> getDestinationIdsByPremiseId(Integer premiseId) {
        String query = "SELECT id FROM premise_destination WHERE premise_id = ?";

        return jdbcTemplate.query(query, (rs, rowNum) -> rs.getInt("id"), premiseId);
    }

    public Integer getRouteCount() {
        String query = """
            SELECT COUNT(*) FROM premise_route
            """;

        return jdbcTemplate.queryForObject(query, Integer.class);
    }

    public Integer getRouteSectionCount() {
        String query = """
            SELECT COUNT(*) FROM premise_route_section
            """;

        return jdbcTemplate.queryForObject(query, Integer.class);
    }

    public Integer getRouteNodeCount() {
        String query = """
            SELECT COUNT(*) FROM premise_route_node
            """;

        return jdbcTemplate.queryForObject(query, Integer.class);
    }

    public List<Route> getRoutesByDestinationId(Integer destinationId) {
        String query = """
            SELECT * FROM premise_route WHERE premise_destination_id = ?
            """;

        return jdbcTemplate.query(query, (rs, rowNum) -> {
            Route entity = new Route();

            entity.setId(rs.getInt("id"));
            entity.setCheapest(rs.getBoolean("is_cheapest"));
            entity.setFastest(rs.getBoolean("is_fastest"));
            entity.setSelected(rs.getBoolean("is_selected"));
            entity.setDestinationId(rs.getInt("premise_destination_id"));

            return entity;
        }, destinationId);
    }

    public Optional<Destination> getDestinationById(Integer id) {

        String query = """
            SELECT * FROM premise_destination WHERE id = ?
            """;

        var destinations = jdbcTemplate.query(query,(rs, row) -> {
            Destination entity = new Destination();

            entity.setId(rs.getInt("id"));
            entity.setAnnualAmount(rs.getInt("annual_amount"));
            entity.setPremiseId(rs.getInt("premise_id"));
            entity.setDestinationNodeId(rs.getInt("destination_node_id"));
            entity.setRateD2d(rs.getBigDecimal("rate_d2d"));
            entity.setD2d(rs.getBoolean("is_d2d"));
            entity.setLeadTimeD2d(rs.getInt("lead_time_d2d"));
            entity.setRepackingCost(rs.getBigDecimal("repacking_cost"));
            entity.setHandlingCost(rs.getBigDecimal("handling_cost"));
            entity.setDisposalCost(rs.getBigDecimal("disposal_cost"));
            entity.setGeoLat(rs.getBigDecimal("geo_lat"));
            entity.setGeoLng(rs.getBigDecimal("geo_lng"));
            entity.setCountryId(rs.getInt("country_id"));

            return entity;
        }, id);

        if(destinations.isEmpty())
            return Optional.empty();

        return Optional.ofNullable(destinations.getFirst());
    }

    public Integer getMaterialIdByPartNumber(String partNumber) {
        String query = "SELECT id FROM material WHERE part_number = ? LIMIT 1";
        return jdbcTemplate.queryForObject(query, Integer.class, partNumber);
    }
}
