package com.bizzan.bitrade.dao;

import org.apache.commons.lang.StringUtils;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExperienceGiftRecordDaoImpl implements ExperienceGiftRecordDaoCustom {

    @PersistenceContext
    private EntityManager entityManager;

    private StringBuilder buildWhere(Long id, Long memberId, Long productId, String productName,
                                     Integer statusGroup, Integer grantType,
                                     String grantStartTime, String grantEndTime,
                                     String expireStartTime, String expireEndTime) {
        StringBuilder where = new StringBuilder(" WHERE 1=1");
        if (id != null) {
            where.append(" AND r.id = ").append(id);
        }
        if (memberId != null) {
            where.append(" AND r.member_id = ").append(memberId);
        }
        if (productId != null) {
            where.append(" AND r.product_id = ").append(productId);
        }
        if (StringUtils.isNotBlank(productName)) {
            where.append(" AND r.product_name LIKE '%").append(productName.replace("'", "''")).append("%'");
        }
        if (grantType != null) {
            where.append(" AND r.grant_type = ").append(grantType);
        }
        if (statusGroup != null) {
            where.append(" AND r.status = ").append(statusGroup);
        }
        if (StringUtils.isNotBlank(grantStartTime)) {
            where.append(" AND r.created_at >= '").append(grantStartTime).append(" 00:00:00'");
        }
        if (StringUtils.isNotBlank(grantEndTime)) {
            where.append(" AND r.created_at <= '").append(grantEndTime).append(" 23:59:59'");
        }
        if (StringUtils.isNotBlank(expireStartTime)) {
            where.append(" AND r.expire_at >= '").append(expireStartTime).append(" 00:00:00'");
        }
        if (StringUtils.isNotBlank(expireEndTime)) {
            where.append(" AND r.expire_at <= '").append(expireEndTime).append(" 23:59:59'");
        }
        return where;
    }

    @Override
    public Page<Map> pageQuery(Long id, Long memberId, Long productId, String productName,
                               Integer statusGroup, Integer grantType,
                               String grantStartTime, String grantEndTime,
                               String expireStartTime, String expireEndTime,
                               int pageNo, int pageSize) {
        StringBuilder where = buildWhere(id, memberId, productId, productName, statusGroup, grantType,
                grantStartTime, grantEndTime, expireStartTime, expireEndTime);

        String countSql = "SELECT COUNT(1) FROM experience_gift_record r" + where;
        String dataSql  = "SELECT r.id, r.member_id memberId, m.username, r.product_name productName," +
                " r.amount, r.max_profit maxProfit, r.leverage, r.validity_days validityDays," +
                " r.grant_type grantType, r.inviter_id inviterId, r.status," +
                " r.expire_at expireAt, r.used_at usedAt, r.closed_at closedAt," +
                " r.coin_symbol coinSymbol, r.position_direction positionDirection," +
                " r.position_id positionId, r.pnl, r.close_reason closeReason," +
                " r.operator_id operatorId, r.operator_remark operatorRemark, r.created_at createdAt" +
                " FROM experience_gift_record r" +
                " LEFT JOIN member m ON m.id = r.member_id" +
                where +
                " ORDER BY r.created_at DESC" +
                " LIMIT " + (pageSize * (pageNo - 1)) + ", " + pageSize;

        long total = ((BigInteger) entityManager.createNativeQuery(countSql).getSingleResult()).longValue();

        Query dataQuery = entityManager.createNativeQuery(dataSql);
        dataQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map> list = dataQuery.getResultList();

        Pageable pageable = new PageRequest(pageNo - 1, pageSize);
        return new PageImpl<>(list, pageable, total);
    }

    @Override
    public Map<String, Object> stats(Long id, Long memberId, Long productId, String productName,
                                     Integer statusGroup, Integer grantType,
                                     String grantStartTime, String grantEndTime,
                                     String expireStartTime, String expireEndTime) {
        StringBuilder where = buildWhere(id, memberId, productId, productName, statusGroup, grantType,
                grantStartTime, grantEndTime, expireStartTime, expireEndTime);

        String sql = "SELECT" +
                " COALESCE(SUM(r.amount), 0) AS totalAmount," +
                " COALESCE(SUM(CASE WHEN r.pnl > 0 THEN r.pnl ELSE 0 END), 0) AS profitAmount," +
                " COALESCE(SUM(CASE WHEN r.pnl < 0 THEN ABS(r.pnl) ELSE 0 END), 0) AS lossAmount" +
                " FROM experience_gift_record r" + where;

        Query query = entityManager.createNativeQuery(sql);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        Map row = (Map) query.getSingleResult();

        Map<String, Object> result = new HashMap<>();
        result.put("totalAmount",  row.get("totalAmount"));
        result.put("profitAmount", row.get("profitAmount"));
        result.put("lossAmount",   row.get("lossAmount"));
        return result;
    }
}
