/**
 * 
 */
package com.platomix.userprofile.handler.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.platomix.userprofile.enums.DsEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.druid.util.StringUtils;
import com.platomix.userprofile.handler.AbstractTagHandler;
import com.platomix.userprofile.model.UserprofileTag;
import com.platomix.userprofile.service.UserprofileTagService;
import com.platomix.userprofile.utils.StrBuilder;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author wookvn
 *	
 *	订购偏好预测
 */
@Slf4j
@Service
public class ForecastOrderTagHandler extends AbstractTagHandler {

	final static String ZT_TABLE_NAME = "ads.ZT_ORDER_PREFERENCE";
	
	@Autowired
	private UserprofileTagService userprofileTagService;
	
	@Override
	public void invoke(String month, String mobileLeft, String mobileRight) {
		List<UserprofileTag> tagList = userprofileTagService.list();
		Map<String, List<UserprofileTag>> tagListMap = tagList.stream().collect(Collectors.groupingBy(t -> t.getEnglishName().toLowerCase()));

		String lrMobileSql = mobileLeft == null || mobileRight == null ? "" : String.format(" and DEVICE_NUMBER>='%s' and DEVICE_NUMBER<'%s'", mobileLeft, mobileRight);

		List<ForecastParam> paramList = new ArrayList<>();
		paramList.add(new ForecastParam(month, "AQY", "爱奇艺", "DeepCross", "", lrMobileSql));
		paramList.add(new ForecastParam(month, "BZ", "哔哩", "DeepCross", lrMobileSql));
		paramList.add(new ForecastParam(month, "KS", "快手", "DeepCross", lrMobileSql));
		paramList.add(new ForecastParam(month, "TX", "腾讯", "DeepCross", lrMobileSql));
		paramList.add(new ForecastParam(month, "YK", "优酷", "DeepCross", lrMobileSql));
		paramList.add(new ForecastParam(month, "MG", "芒果", "DeepCross", lrMobileSql));
		
		paramList.add(new ForecastParam(month, "AQY", "爱奇艺", "XGBoost", lrMobileSql));
		paramList.add(new ForecastParam(month, "BZ", "哔哩", "XGBoost", lrMobileSql));
		paramList.add(new ForecastParam(month, "KS", "快手", "XGBoost", lrMobileSql));
		paramList.add(new ForecastParam(month, "TX", "腾讯", "XGBoost", lrMobileSql));
		paramList.add(new ForecastParam(month, "YK", "优酷", "XGBoost", lrMobileSql));
		paramList.add(new ForecastParam(month, "MG", "芒果", "XGBoost", lrMobileSql));
		
		StrBuilder sqlBuilder = new StrBuilder();
		sqlBuilder.appendLn(super.buildTableSql(ZT_TABLE_NAME, "THEMONTH_PRE", "USERID_PRE"));
		sqlBuilder.append("select ").append("'"+month+"'").appendLn(" as THEMONTH_PRE,").appendLn("multiIf(");
		for(ForecastParam param : paramList) {
			sqlBuilder.appendLn(String.format("%s.USERID != '', %s.USERID, ", param.getTableAlias(), param.getTableAlias()));
		}
		sqlBuilder.appendLn("'err') as USERID_PRE,");
		for(ForecastParam param : paramList) {
			String columnName = param.getEnglishName().toUpperCase(),
				   columnNameC = columnName+"_C", columnNameV = columnName+"_V";
			sqlBuilder.appendLn(String.format("%s.%s as %s,", param.getTableAlias(), columnName, columnName));
			sqlBuilder.appendLn(String.format("%s.%s as %s,", param.getTableAlias(), columnNameC, columnNameC));
			sqlBuilder.appendLn(String.format("%s.%s as %s,", param.getTableAlias(), columnNameV, columnNameV));
		}
		sqlBuilder.deleteLastChar().deleteLastChar().appendLn("").appendLn("from");
		for(ForecastParam param : paramList) {
			sqlBuilder.appendLn(_genOrderPreferenceSql(param, tagListMap));
		}
		log.info("\n" + sqlBuilder.toString());
		dynamicExecuteService.execute(DsEnum.clickhouse, sqlBuilder.toString(), "订购偏好预测[临时表]生成");
	}
	
	/**
	 * 
	 * @param param
	 * @return
	 */
	private String _genOrderPreferenceSql(ForecastParam param, Map<String, List<UserprofileTag>> tagListMap) {
		StrBuilder sqlBuilder = new StrBuilder();
		sqlBuilder.append(param.getJoinStr()).appendLn("(select USERID,");
		String englishName = param.getEnglishName();
		String fragmentSql = genBucketSql(englishName, "CANCEL_P1", "CANCEL_P2", tagListMap.get(englishName));
		sqlBuilder.appendLn(fragmentSql);
		
		String valueStr  = "XGBoost".equalsIgnoreCase(param.getAlgName()) ? "PRO_RESULT" : "`1_PRO_RESULT`",
			   value1Str = "XGBoost".equalsIgnoreCase(param.getAlgName()) ? "RESULT" : "result",
			   tableName = String.format("ads.ADS_ORDER_PRE_%s_%s_%s", param.getAlgName(), param.getTp(), value1Str);
		sqlBuilder.appendLn("from")
		          .appendLn("(")
				  .appendLn("select DEVICE_NUMBER as  USERID,intDiv("+valueStr+"*100,10)*10 as CANCEL_P1,"+valueStr+"*100 as CANCEL_P2")
				  .appendLn("from " + tableName)
				  .append("where 1 = 1").appendLn(param.getLrMobileSql())
				  .appendLn(") t")
				  .appendLn(") " + param.getTableAlias());
		if(!StringUtils.isEmpty(param.getJoinStr())) {
			sqlBuilder.appendLn(" on tDeepCross_AQY.USERID="+param.getTableAlias()+".USERID");
		}
		return sqlBuilder.toString();
	}

	@Override
	public boolean executeInBatchs() {
		return true;
	}
	
	@Data
	@NoArgsConstructor
	static class ForecastParam{
		private String month;
		private String tp;
		private String tpName;
		private String algName;
		private String joinStr = " full outer join ";
		private String lrMobileSql;
		
		final static Map<String, String> nameMap = new HashMap<>();
		static {
			nameMap.put("AQY", "aiqiyi");
			nameMap.put("KS", "kuaishou");
			nameMap.put("TX", "tencent");
			nameMap.put("MG", "mangtv");
			nameMap.put("YK", "youku");
			nameMap.put("BZ", "bilibili");
		}
		/**
		 * @param month
		 * @param tp
		 * @param tpName
		 * @param tableAlsStr
		 * @param lrMobileSql
		 */
		public ForecastParam(String month, String tp, String tpName, String algName, String lrMobileSql) {
			super();
			this.month = month;
			this.tp = tp;
			this.tpName = tpName;
			this.algName = algName;
			this.lrMobileSql = lrMobileSql;
		}
		/**
		 * @param month
		 * @param tp
		 * @param tpName
		 * @param tableAlsStr
		 * @param joinStr
		 * @param lrMobileSql
		 */
		public ForecastParam(String month, String tp, String tpName, String algName, String joinStr,
				String lrMobileSql) {
			super();
			this.month = month;
			this.tp = tp;
			this.tpName = tpName;
			this.algName = algName;
			this.joinStr = joinStr;
			this.lrMobileSql = lrMobileSql;
		}
		
		public String getLongTp() {
			return nameMap.get(tp);
		}
		
		public String getTableAlias() {
			return String.format("t%s_%s", algName, tp);
		}
		
		public String getEnglishName() {
			return String.format("als_order_%s_%s", getLongTp(), 
					"DeepCross".equalsIgnoreCase(algName) ? "dec" : "xgb");
		}
		
	}
}
