package de.avatic.lcc.repositories.premise;

import de.avatic.lcc.dto.generic.RateType;
import de.avatic.lcc.dto.generic.TransportType;
import de.avatic.lcc.model.db.premises.route.RouteSection;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Repository
public class RouteSectionRepository {


    private final JdbcTemplate jdbcTemplate;

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

    public List<RouteSection> getByRouteId(Integer routeId) {
        String query = "SELECT * FROM premise_route_section WHERE premise_route_id = ?";

        return jdbcTemplate.query(query, new RouteSectionMapper(), routeId);
    }

    public void deleteAllById(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }

        String placeholders = String.join(",", Collections.nCopies(ids.size(), "?"));
        String sql = "DELETE FROM premise_route_section WHERE id IN (" + placeholders + ")";

        jdbcTemplate.update(sql, ids.toArray(new Object[0]));
    }

    public Integer insert(RouteSection premiseRouteSection) {
        String sql = "INSERT INTO premise_route_section (premise_route_id, from_route_node_id, to_route_node_id, list_position, transport_type, rate_type, is_pre_run, is_main_run, is_post_run, is_outdated) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        KeyHolder keyHolder = new GeneratedKeyHolder();

        jdbcTemplate.update(connection -> {
            PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            ps.setInt(1, premiseRouteSection.getRouteId());
            ps.setInt(2, premiseRouteSection.getFromRouteNodeId());
            ps.setInt(3, premiseRouteSection.getToRouteNodeId());
            ps.setInt(4, premiseRouteSection.getListPosition());
            ps.setString(5, premiseRouteSection.getTransportType().name());
            ps.setString(6, premiseRouteSection.getRateType().name());
            ps.setBoolean(7, premiseRouteSection.getPreRun());
            ps.setBoolean(8, premiseRouteSection.getMainRun());
            ps.setBoolean(9, premiseRouteSection.getPostRun());
            ps.setBoolean(10, premiseRouteSection.getOutdated());
            return ps;
        }, keyHolder);

        return keyHolder.getKey() != null ? keyHolder.getKey().intValue() : null;
    }

    public Optional<RouteSection> getById(Integer id) {
        String query = "SELECT * FROM premise_route_section WHERE id = ?";
        var section = jdbcTemplate.query(query, new RouteSectionMapper(), id);
        return section.isEmpty() ? Optional.empty() : Optional.of(section.getFirst());
    }

    private static class RouteSectionMapper implements RowMapper<RouteSection> {
        @Override
        public RouteSection mapRow(ResultSet rs, int rowNum) throws SQLException {
            RouteSection entity = new RouteSection();

            entity.setId(rs.getInt("id"));
            entity.setRouteId(rs.getInt("premise_route_id"));
            entity.setFromRouteNodeId(rs.getInt("from_route_node_id"));
            entity.setToRouteNodeId(rs.getInt("to_route_node_id"));
            entity.setListPosition(rs.getInt("list_position"));

            entity.setTransportType(TransportType.valueOf(rs.getString("transport_type")));
            entity.setRateType(RateType.valueOf(rs.getString("rate_type")));

            entity.setPreRun(rs.getBoolean("is_pre_run"));
            entity.setMainRun(rs.getBoolean("is_main_run"));
            entity.setPostRun(rs.getBoolean("is_post_run"));
            entity.setOutdated(rs.getBoolean("is_outdated"));

            return entity;
        }
    }
}
