package de.avatic.lcc.repositories.packaging;

import de.avatic.lcc.model.db.packaging.PackagingDimension;
import de.avatic.lcc.model.db.packaging.PackagingType;
import de.avatic.lcc.model.db.utils.DimensionUnit;
import de.avatic.lcc.model.db.utils.WeightUnit;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Objects;
import java.util.Optional;

@Repository
public class PackagingDimensionRepository {

    private final JdbcTemplate jdbcTemplate;

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

    @Transactional
    public Optional<PackagingDimension> getById(Integer id) {
        String query = """
            SELECT id, displayed_dimension_unit, displayed_weight_unit, width, length, height,
                   weight, content_unit_count, type, is_deprecated
            FROM packaging_dimension
            WHERE packaging_dimension.id = ? AND packaging_dimension.is_deprecated = false""";


            //TODO: what if i need to get deprecated materials?

        var dimension = jdbcTemplate.query(query, (rs, rowNum) -> {
            var entity = new PackagingDimension();

            entity.setId(rs.getInt("id"));
            entity.setDimensionUnit(DimensionUnit.valueOf(rs.getString("displayed_dimension_unit")));
            entity.setWeightUnit(WeightUnit.valueOf(rs.getString("displayed_weight_unit")));
            entity.setType(PackagingType.valueOf(rs.getString("type")));
            entity.setDeprecated(rs.getBoolean("is_deprecated"));

            entity.setWeight(rs.getInt("weight"));

            entity.setWidth(rs.getInt("width"));
            entity.setHeight(rs.getInt("height"));
            entity.setLength(rs.getInt("length"));

            entity.setContentUnitCount(rs.getInt("content_unit_count"));

            return entity;
        }, id);

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

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

    public void update(PackagingDimension dimension) {
        DimensionUnit shuDimensionUnit = dimension.getDimensionUnit();
        WeightUnit shuWeightUnit = dimension.getWeightUnit();

        String huQuery = """
                UPDATE packaging_dimension SET type = ?, width = ?, length = ?, height = ?, weight = ?,
                displayed_dimension_unit = ?, displayed_weight_unit = ?, content_unit_count = ?,
                is_deprecated = ? WHERE id = ?""";


        jdbcTemplate.update(huQuery,
                dimension.getType().name(),
                dimension.getWidth(),
                dimension.getLength(),
                dimension.getHeight(),
                dimension.getWeight(),
                dimension.getDimensionUnit().name(),
                dimension.getWeightUnit().name(),
                dimension.getContentUnitCount(),
                dimension.getDeprecated(),
                dimension.getId());
    }


    public Optional<Integer> insert(PackagingDimension entity) {

        KeyHolder keyHolder = new GeneratedKeyHolder();

        jdbcTemplate.update(connection -> {

            PreparedStatement ps = connection
                    .prepareStatement("INSERT INTO packaging_dimension (type, length, width, height, displayed_dimension_unit, weight, displayed_weight_unit, content_unit_count, is_deprecated) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                            Statement.RETURN_GENERATED_KEYS);

            ps.setString(1, entity.getType().name());  //
            ps.setInt(2, entity.getLength());
            ps.setInt(3, entity.getWidth());
            ps.setInt(4,  entity.getHeight());
            ps.setString(5,  entity.getDimensionUnit().name());
            ps.setInt(6,  entity.getWeight());
            ps.setString(7,  entity.getWeightUnit().name());
            ps.setInt(8,  entity.getContentUnitCount());
            ps.setBoolean(9, entity.getDeprecated());
            return ps;
        }, keyHolder);


        return Optional.ofNullable(!Objects.requireNonNull(keyHolder.getKeys()).isEmpty() ? ((Integer) keyHolder.getKeys().values().iterator().next())
                : null);
    }

    public Optional<Integer> setDeprecatedById(Integer id) {
        String query = "UPDATE packaging_dimension SET is_deprecated = TRUE WHERE id = ?";
        return Optional.ofNullable(jdbcTemplate.update(query, id) == 0 ? null : id);
    }

}
