package com.utopiaindustries.dao.uind;

import com.utopiaindustries.util.KeyHolderFunctions;
import com.utopiaindustries.model.uind.LocationSite;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Repository
public class LocationSiteDAO {

    private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    private final String TABLE_NAME = "inventory.location_site";
    private final String SELECT_QUERY = String.format("SELECT * FROM %s WHERE id = :id", TABLE_NAME);
    private final String SELECT_ALL_QUERY = String.format("SELECT * FROM %s ORDER BY title ASC", TABLE_NAME);
    private final String DELETE_QUERY = String.format("DELETE FROM %s WHERE id = :id", TABLE_NAME);
    private final String INSERT_QUERY = String.format("INSERT INTO %s (id, title, short_title, address, has_colony) VALUES (:id, :title, :short_title, :address, :has_colony) ON DUPLICATE KEY UPDATE title = :title, short_title = :short_title, address = :address, has_colony = :has_colony", TABLE_NAME);
    private final String SELECT_BY_IDS_QUERY = String.format("SELECT * FROM %s WHERE id IN ( :ids ) order by id asc", TABLE_NAME);

    public LocationSiteDAO(@Qualifier("namedParameterJdbcTemplateUind") NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
        this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    }

    // prepare query params
    private MapSqlParameterSource prepareInsertQueryParams(LocationSite locationSite) {
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", locationSite.getId())
                .addValue("title", locationSite.getTitle())
                .addValue("short_title", locationSite.getShortTitle())
                .addValue("address", locationSite.getAddress())
                .addValue("has_colony", locationSite.getHasColony());
        return params;
    }

    // find
    public LocationSite find(long id) {
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        return namedParameterJdbcTemplate.query(SELECT_QUERY, params, new LocationSiteRowMapper())
                .stream()
                .findFirst()
                .orElse( new LocationSite() );
    }

    // find all
    public List<LocationSite> findAll() {
        return namedParameterJdbcTemplate.query(SELECT_ALL_QUERY, new LocationSiteRowMapper());
    }

    // save
    public long save(LocationSite locationSite) {
        KeyHolder keyHolder = new GeneratedKeyHolder();
        MapSqlParameterSource params = prepareInsertQueryParams(locationSite);
        namedParameterJdbcTemplate.update(INSERT_QUERY, params, keyHolder);
        return KeyHolderFunctions.getKey(locationSite.getId(), keyHolder);
    }

    // save all
    public int[] saveAll(List<LocationSite> locationSites) {
        List<MapSqlParameterSource> batchArgs = new ArrayList<>();
        for (LocationSite locationSite : locationSites) {
            MapSqlParameterSource params = prepareInsertQueryParams(locationSite);
            batchArgs.add(params);
        }
        return namedParameterJdbcTemplate.batchUpdate(INSERT_QUERY, batchArgs.toArray(new MapSqlParameterSource[locationSites.size()]));
    }

    // delete
    public boolean delete(long id) {
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        return namedParameterJdbcTemplate.update(DELETE_QUERY, params) > 0;
    }

    // find by ids
    public List<LocationSite> findByIds(Set<Long> ids) {
        if (ids != null && !ids.isEmpty()) {
            MapSqlParameterSource params = new MapSqlParameterSource();
            params.addValue("ids", ids);
            return namedParameterJdbcTemplate.query(SELECT_BY_IDS_QUERY, params, new LocationSiteRowMapper());
        }
        return new ArrayList<>();
    }

    // find by ids
    public List<LocationSite> findByLongIds(List<Long> ids) {
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("ids", ids);
        return namedParameterJdbcTemplate.query(SELECT_BY_IDS_QUERY, params, new LocationSiteRowMapper());
    }
}
