package de.avatic.lcc.repositories.packaging;

import de.avatic.lcc.model.db.properties.PackagingProperty;
import de.avatic.lcc.model.db.properties.PropertyDataType;
import de.avatic.lcc.model.db.properties.PropertyType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;

@Repository
public class PackagingPropertiesRepository {

    private final JdbcTemplate jdbcTemplate;

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

    public List<PackagingProperty> getByPackagingId(Integer id) {

        String query = """
                SELECT property.id as id, property.property_value AS value, property.packaging_id as packaging_id,
                       type.id AS type_id, type.name AS type_name, type.data_type AS type_data_type, type.is_required AS type_is_required,
                       type.external_mapping_id AS type_external_mapping_id, type.validation_rule AS type_validation_rule
                FROM packaging_property property LEFT JOIN packaging_property_type type ON property.packaging_property_type_id = type.id WHERE packaging_id = ?""";

        return jdbcTemplate.query(query, new PropertyMapper(), id);

    }

    public Optional<PackagingProperty> getByPackagingIdAndType(Integer id, String type) {
        String query = """
                SELECT property.id as id, property.property_value AS value, property.packaging_id as packaging_id,
                       type.id AS type_id, type.name AS type_name, type.data_type AS type_data_type, type.is_required AS type_is_required,
                       type.external_mapping_id AS type_external_mapping_id, type.validation_rule AS type_validation_rule
                FROM packaging_property property LEFT JOIN packaging_property_type type ON property.packaging_property_type_id = type.id WHERE packaging_id = ? AND type.external_mapping_id = ?""";

        var property =  jdbcTemplate.query(query, new PropertyMapper(), id, type);

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

        return Optional.of(property.getFirst());

    }


    private static class PropertyMapper implements RowMapper<PackagingProperty> {
        @Override
        public PackagingProperty mapRow(ResultSet rs, int rowNum) throws SQLException {
            PackagingProperty property = new PackagingProperty();
            PropertyType type = new PropertyType();

            type.setId(rs.getInt("type_id"));
            type.setName(rs.getString("type_name"));
            type.setDataType(PropertyDataType.valueOf(rs.getString("type_data_type")));
            type.setRequired(rs.getBoolean("type_is_required"));
            type.setExternalMappingId(rs.getString("type_external_mapping_id"));
            type.setValidationRule(rs.getString("type_validation_rule"));

            property.setType(type);
            property.setId(rs.getInt("id"));
            property.setPackagingId(rs.getInt("packaging_id"));
            property.setValue(rs.getString("value"));

            return property;
        }
    }


    public List<PropertyType> listTypes() {
        String query = """
                SELECT * FROM packaging_property_type
                """;

        return jdbcTemplate.query(query, (rs, rowNum) -> {
            PropertyType type = new PropertyType();

            type.setId(rs.getInt("id"));
            type.setName(rs.getString("name"));
            type.setDataType(PropertyDataType.valueOf(rs.getString("data_type")));
            type.setRequired(rs.getBoolean("is_required"));
            type.setExternalMappingId(rs.getString("external_mapping_id"));
            type.setValidationRule(rs.getString("validation_rule"));

            return type;
        });
    }


    public void update(Integer packagingId, Integer typeId, String value) {
        String query = """
                        INSERT INTO packaging_property (property_value, packaging_id, packaging_property_type_id) VALUES (?, ?, ?)
                        ON DUPLICATE KEY UPDATE property_value = ?""";

        jdbcTemplate.update(query, value, packagingId, typeId, value);
    }

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

    public void update(Integer packagingId, String typeId, String value) {

        String query = """
                        INSERT INTO packaging_property (property_value, packaging_id, packaging_property_type_id) VALUES (?, ?, ?)
                        ON DUPLICATE KEY UPDATE property_value = ?""";

        jdbcTemplate.update(query, value, packagingId, typeId, value);
    }

}
