package com.utopiaindustries.dao.ctp;

import com.utopiaindustries.dao.uind.PurchaseOrderRowMapper;
import com.utopiaindustries.model.ctp.JobCard;
import com.utopiaindustries.model.ctp.PurchaseOrderCTP;
import com.utopiaindustries.model.uind.PurchaseOrder;
import com.utopiaindustries.util.KeyHolderFunctions;
import org.springframework.beans.factory.annotation.Autowired;
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 PurchaseOrderCTPDao {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    private final String TABLE_NAME = "cut_to_pack.purchase_order";
    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 created_at DESC LIMIT :limit ", TABLE_NAME );
    private final String SELECT_BY_PO_CODE = String.format("SELECT * FROM %s WHERE purchase_order_code = :purchase_order_code ORDER BY created_at DESC LIMIT :limit", 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, purchase_order_code, purchase_order_quantity, purchase_order_quantity_required, article_name, created_by, status, po_status) " +
                    "VALUES (:id, :purchase_order_code, :purchase_order_quantity, :purchase_order_quantity_required, :article_name, :created_by, :status, :po_status) " +
                    "ON DUPLICATE KEY UPDATE " +
                    "purchase_order_code = VALUES(purchase_order_code), " +
                    "purchase_order_quantity = VALUES(purchase_order_quantity), " +
                    "purchase_order_quantity_required = VALUES(purchase_order_quantity_required), " +
                    "article_name = VALUES(article_name), " +
                    "created_by = VALUES(created_by), " +
                    "status = VALUES(status)," +
                    "po_status = VALUES(po_status)",
            TABLE_NAME);

    private final String SELECT_BY_LIMIT = String.format( "SELECT * FROM %s WHERE created_by = :created_by ORDER BY id ASC limit :limit", TABLE_NAME );
    private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE purchase_order_code LIKE :term AND po_status = false limit 100 offset 0", TABLE_NAME );


    // prepare query params
    private MapSqlParameterSource prepareInsertQueryParams(PurchaseOrderCTP purchaseOrderCTP) {
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", purchaseOrderCTP.getId())
                .addValue("purchase_order_code", purchaseOrderCTP.getPurchaseOrderCode())
                .addValue("purchase_order_quantity", purchaseOrderCTP.getPurchaseOrderQuantity())
                .addValue("purchase_order_quantity_required", purchaseOrderCTP.getPurchaseOrderQuantityRequired())
                .addValue("article_name", purchaseOrderCTP.getArticleName())
                .addValue("created_by", purchaseOrderCTP.getCreatedBy())
                .addValue("status", purchaseOrderCTP.getStatus())
                .addValue("po_status", purchaseOrderCTP.getPoStatus());
        return params;
    }


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


    // find all
    public List<PurchaseOrderCTP> findAll(Long limit) {
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("limit", limit);
        return namedParameterJdbcTemplate.query( SELECT_ALL_QUERY, params, new PurchaseOrderCTPRowMapper() );
    }

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

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

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

    /*
     * find by query
     * */
    public List<PurchaseOrderCTP> findByQuery(String query ){
        return namedParameterJdbcTemplate.query( query, new PurchaseOrderCTPRowMapper() );
    }

    /*
    * find by created by
    * */
    public List<PurchaseOrderCTP> findByUserAndLimit(String createdBy, Long limit ){
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("limit", limit.intValue() );
        params.addValue("created_by", createdBy );
        return namedParameterJdbcTemplate.query( SELECT_BY_LIMIT, params, new PurchaseOrderCTPRowMapper() );
    }

    /*
    * find by po code
    * */
    public List<PurchaseOrderCTP> findByPoCode(String poCode, Long limit ){
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("purchase_order_code", poCode);
        params.addValue("limit", limit);
        return namedParameterJdbcTemplate.query( SELECT_BY_PO_CODE, params, new PurchaseOrderCTPRowMapper() );
    }

    /*
     * find by term
     * */
    public List<PurchaseOrderCTP> findByTerm(String term ){
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("term", "%" + term + "%" );
        return namedParameterJdbcTemplate.query( SELECT_BY_TERM, params, new PurchaseOrderCTPRowMapper() );
    }
}
