package com.utopiaindustries.dao.ctp;

import com.utopiaindustries.model.ctp.FinishedItem;
import com.utopiaindustries.model.ctp.PackagingItems;
import com.utopiaindustries.util.KeyHolderFunctions;
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;

@Repository
public class PackagingItemsDAO {

    private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    private static final String TABLE_NAME = "packaging_items";

    private static final String SELECT_BY_ID = String.format("SELECT * FROM %s WHERE id = :id", TABLE_NAME);
    private static final String SELECT_ALL = String.format("SELECT * FROM %s ORDER BY id DESC", TABLE_NAME);
    private static final String DELETE_BY_ID = String.format("DELETE FROM %s WHERE id = :id", TABLE_NAME);
    private static final String SELECT_BY_JOB_CARD_ID = String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id", TABLE_NAME);

    private static final String INSERT_QUERY = String.format(
            "INSERT INTO %s (" +
                    "id, item_id, sku, barcode, job_card_id, created_at, created_by, " +
                    "is_qa, finish_item_id, is_segregated, account_id, qa_status, bundle_id, account_title" +
                    ") VALUES (" +
                    ":id, :item_id, :sku, :barcode, :job_card_id, :created_at, :created_by, " +
                    ":is_qa, :finish_item_id, :is_segregated, :account_id, :qa_status, :bundle_id, :account_title" +
                    ") ON DUPLICATE KEY UPDATE " +
                    "item_id = VALUES(item_id), sku = VALUES(sku), barcode = VALUES(barcode), " +
                    "job_card_id = VALUES(job_card_id), created_at = VALUES(created_at), created_by = VALUES(created_by), " +
                    "is_qa = VALUES(is_qa), finish_item_id = VALUES(finish_item_id), " +
                    "is_segregated = VALUES(is_segregated), account_id = VALUES(account_id), " +
                    "qa_status = VALUES(qa_status), bundle_id = VALUES(bundle_id), account_title = VALUES(account_title)",
            TABLE_NAME
    );
    private final String SELECT_BY_DATE_AND_IDs = String.format( "SELECT COUNT(*) FROM %s WHERE (:start_date IS NULL OR  created_at >=:start_date) AND created_at <= :end_date AND id IN (:ids)", TABLE_NAME );

    public PackagingItemsDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
        this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    }

    private MapSqlParameterSource prepareParams(PackagingItems item) {
        return new MapSqlParameterSource()
                .addValue("id", item.getId())
                .addValue("item_id", item.getItemId())
                .addValue("sku", item.getSku())
                .addValue("barcode", item.getBarcode())
                .addValue("job_card_id", item.getJobCardId())
                .addValue("created_at", item.getCreatedAt())
                .addValue("created_by", item.getCreatedBy())
                .addValue("is_qa", item.getIsQa())
                .addValue("finish_item_id", item.getFinishedItemId())
                .addValue("is_segregated", item.getIsSegregated())
                .addValue("account_id", item.getAccountId())
                .addValue("qa_status", item.getQaStatus())
                .addValue("bundle_id", item.getBundleId())
                .addValue("account_title", item.getAccountTitle());
    }

    public PackagingItems find(long id) {
        MapSqlParameterSource params = new MapSqlParameterSource("id", id);
        return namedParameterJdbcTemplate.query(SELECT_BY_ID, params, new PackagingItemsRowMapper())
                .stream().findFirst().orElse(new PackagingItems());
    }

    public List<PackagingItems> findAll() {
        return namedParameterJdbcTemplate.query(SELECT_ALL, new PackagingItemsRowMapper());
    }

    public long save(PackagingItems item) {
        KeyHolder keyHolder = new GeneratedKeyHolder();
        MapSqlParameterSource params = prepareParams(item);
        namedParameterJdbcTemplate.update(INSERT_QUERY, params, keyHolder);
        return KeyHolderFunctions.getKey(item.getId(), keyHolder);
    }

    public int[] saveAll(List<PackagingItems> items) {
        List<MapSqlParameterSource> batchParams = new ArrayList<>();
        for (PackagingItems item : items) {
            batchParams.add(prepareParams(item));
        }
        return namedParameterJdbcTemplate.batchUpdate(INSERT_QUERY, batchParams.toArray(new MapSqlParameterSource[0]));
    }

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

    public List<PackagingItems> findByJobCardId(long jobCardId) {
        MapSqlParameterSource params = new MapSqlParameterSource("job_card_id", jobCardId);
        return namedParameterJdbcTemplate.query(SELECT_BY_JOB_CARD_ID, params, new PackagingItemsRowMapper());
    }

    public Long findByDateAndIds(String startDate, String endDate,List<Long> ids){
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue( "start_date", startDate );
        params.addValue( "end_date", endDate );
        params.addValue( "ids", ids );
        Long count = namedParameterJdbcTemplate.queryForObject(SELECT_BY_DATE_AND_IDs, params, Long.class);
        return count != null ? count : 0;
    }
}

