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

import java.time.LocalDate;
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.platomix.userprofile.handler.AbstractTagHandler;
import com.platomix.userprofile.model.UserprofileTag;
import com.platomix.userprofile.service.UserprofileTagService;
import com.platomix.userprofile.utils.StrBuilder;

import lombok.extern.slf4j.Slf4j;

/**
 * @author wookvn
 *
 *	信息化标签生成
 */
@Slf4j
@Service
public class XxhTagHandler extends AbstractTagHandler{
	
	final static String ZT_TABLE_NAME = "ads.ZT_USER_TAG_XXH";
	final static long _STEP=50000000L;
	@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);
		StrBuilder sqlBuilder = new StrBuilder();
		sqlBuilder.appendLn(super.buildTableSql(ZT_TABLE_NAME, "MONTH_ID", "DEVICE_NUMBER"));
		sqlBuilder.append("select DEVICE_NUMBER,").append("'"+month+"'").appendLn(" as MONTH_ID,");
		int year = LocalDate.now().getYear();
		
		//大网标签-入网时长
		appendTagIntime(year, sqlBuilder, tagListMap);
		sqlBuilder.appendLn(",");
		
		//大网标签-套餐价格
		appendTagPackagePic(sqlBuilder, tagListMap);
		sqlBuilder.appendLn(",");
		
		//大网标签-月流量消耗
		appendEventFlux(sqlBuilder, tagListMap);
		sqlBuilder.appendLn(",");
		
		//大网标签-月消费
		appendEventConsume(sqlBuilder, tagListMap);
		sqlBuilder.appendLn(",");
		
		//大网标签-手机品牌
		String phoneTypeSql = userprofileTagService.genSelectSql("手机品牌", "MANU_NAME", null, null);
		sqlBuilder.append(phoneTypeSql).appendLn(",");
		
		//大网标签-视频流量消耗
		appendTotalFluxVideo(sqlBuilder, tagListMap);
		sqlBuilder.appendLn(",");
		
		//大网标签-是否出账
		appendEventIsAcct(sqlBuilder, tagListMap);
		sqlBuilder.appendLn(",");
		
		//产品标签-退订产品状态
		appendEventCancelProd(sqlBuilder);
		sqlBuilder.appendLn("");
		
		//From表
		sqlBuilder.appendLn("from (")
				  .appendLn("select  MONTH_ID,DEVICE_NUMBER, PROV_DESC, SERVICE_TYPE, INNET_MONTHS, CUST_SEX, CERT_AGE,")
				  .appendLn(" TOTAL_FLUX, TOTAL_FEE, MON_TOTAL_FEE, any(PRODUCT_CLASS_DESC) as PRODUCT_CLASS_DESC, MAX(MON_FEE) as MON_FEE,")
				  .appendLn(" FLUX_M, RESOURCE_NAME, PKG_NAME, MANU_NAME, MODEL_NAME, IS_ACCT, MAX(TOTAL_FLUX_VIDEO) as TOTAL_FLUX_VIDEO,")
				  .appendLn(" groupArray(CANCEL_TYPE) as CANCEL_TYPE")
				  .appendLn(" from")
				  .appendLn("( SELECT  MONTH_ID, DEVICE_NUMBER, PROV_DESC, SERVICE_TYPE, INNET_MONTHS, CUST_SEX, CERT_AGE, TOTAL_FLUX, TOTAL_FEE, MON_TOTAL_FEE, PRODUCT_CLASS_DESC, MON_FEE, FLUX_M, RESOURCE_NAME, PKG_NAME, MANU_NAME, MODEL_NAME, IS_ACCT, TOTAL_FLUX_VIDEO")
				  .appendLn(" ,'dg' as CANCEL_TYPE")
				  .appendLn(" FROM ads.XXH_ALL_MONTH where MONTH_ID = '"+month+"'" + lrMobileSql)
				  .appendLn(" union all")
				  .append(" SELECT  MONTH_ID, DEVICE_NUMBER, PROV_DESC, SERVICE_TYPE, INNET_MONTHS, CUST_SEX, CERT_AGE, TOTAL_FLUX, TOTAL_FEE, MON_TOTAL_FEE, PRODUCT_CLASS_DESC, MON_FEE, FLUX_M, RESOURCE_NAME, PKG_NAME, MANU_NAME, MODEL_NAME, IS_ACCT, TOTAL_FLUX_VIDEO,CANCEL_TYPE")
				  .append(" FROM ads.XXH_ALL_CANCEL_MONTH xacm where MONTH_ID = '"+month+"'" + lrMobileSql)
				  .appendLn(") s group by MONTH_ID,DEVICE_NUMBER, PROV_DESC, SERVICE_TYPE, INNET_MONTHS, CUST_SEX, CERT_AGE,")
				  .appendLn("TOTAL_FLUX, TOTAL_FEE, MON_TOTAL_FEE,FLUX_M, RESOURCE_NAME, PKG_NAME, MANU_NAME, MODEL_NAME, IS_ACCT")
				  .appendLn(") t");
		log.info("\n" + sqlBuilder.toString());
		dynamicExecuteService.execute(DsEnum.clickhouse, sqlBuilder.toString(), "信息化标签生成");
	}
	
	/**
	 * 入网时长
	 * @return
	 */
	public void appendTagIntime(int year, StrBuilder sqlBuilder, Map<String, List<UserprofileTag>> tagListMap) {
		/**
		 * (case when (${yearStr}- floor(INNET_MONTHS*0.0001))>=20 then 'A112_07_001'
			when  (${yearStr}- floor(INNET_MONTHS*0.0001))>=10 and (2020- floor(INNET_MONTHS*0.0001))<20 then 'A112_07_002'
			when (${yearStr}- floor(INNET_MONTHS*0.0001))>=5 and (2020- floor(INNET_MONTHS*0.0001))<10 then 'A112_07_003'
			when (${yearStr}- floor(INNET_MONTHS*0.0001))>=2 and (2020- floor(INNET_MONTHS*0.0001))<5 then 'A112_07_004'
			when  (${yearStr}- floor(INNET_MONTHS*0.0001))>=1 and (2020- floor(INNET_MONTHS*0.0001))<2 then 'A112_07_005'
			when  (${yearStr}- floor(INNET_MONTHS*0.0001))<1 and (2020- floor(INNET_MONTHS*0.0001))>=0 then 'A112_07_006'
			else 'A112_07_007' end) TAG_INTIME ,
		 */
		String function = "("+year+" - floor(INNET_MONTHS*0.0001))";
		
		String sql = genBucketSql("tag_intime", function, function, tagListMap.get("tag_intime"));
		sqlBuilder.append(sql);
	}
	
	/**
	 * 套餐价格
	 * @param sqlBuilder
	 * @param tagMap
	 */
	public void appendTagPackagePic(StrBuilder sqlBuilder, Map<String, List<UserprofileTag>> tagListMap) {
		/**
		 * (case when toFloat32OrNull(MON_FEE)<10 then 'A112_09_001'
			when toFloat32OrNull(MON_FEE)>=10 and toFloat32OrNull(MON_FEE)<20 then 'A112_09_002'
			when  toFloat32OrNull(MON_FEE)>=20 and toFloat32OrNull(MON_FEE)<60  then 'A112_09_003'
			when  toFloat32OrNull(MON_FEE)>=60 and toFloat32OrNull(MON_FEE)<100  then 'A112_09_004'
			when  toFloat32OrNull(MON_FEE)>=100 and toFloat32OrNull(MON_FEE)<150  then 'A112_09_005'
			when  toFloat32OrNull(MON_FEE)>=150 and toFloat32OrNull(MON_FEE)<300  then 'A112_09_006'
			when  toFloat32OrNull(MON_FEE)>=300  then 'A112_09_007'
			else 'A112_09_008' end) TAG_PACKAGE_PIC,
		 */
		String sql = genBucketSql("tag_package_pic", "toFloat32OrNull(MON_FEE)", "toFloat32OrNull(MON_FEE)", tagListMap.get("tag_package_pic"));
		sqlBuilder.append(sql);
	}
	
	/**
	 * 大网标签-月流量消耗
	 * @param sqlBuilder
	 * @param tagMap
	 */
	public void appendEventFlux(StrBuilder sqlBuilder, Map<String, List<UserprofileTag>> tagListMap) {
		/**
		 * (case when  toFloat64OrZero(TOTAL_FLUX)<=0  then 'B112_01_001'
			when  toFloat64OrZero(TOTAL_FLUX)>0 and toFloat64OrZero(TOTAL_FLUX)<=500 then 'B112_01_002'
			when   toFloat64OrZero(TOTAL_FLUX)>500 and toFloat64OrZero(TOTAL_FLUX)<=2000  then 'B112_01_003'
			when   toFloat64OrZero(TOTAL_FLUX)>2000 and toFloat64OrZero(TOTAL_FLUX)<=5000  then 'B112_01_004'
			when   toFloat64OrZero(TOTAL_FLUX)>5000 and toFloat64OrZero(TOTAL_FLUX)<=10000  then 'B112_01_005'
			when   toFloat64OrZero(TOTAL_FLUX)>10000 and toFloat64OrZero(TOTAL_FLUX)<=15000  then 'B112_01_006'
			when   toFloat64OrZero(TOTAL_FLUX)>15000 and toFloat64OrZero(TOTAL_FLUX)<=30000  then 'B112_01_007'
			when   toFloat64OrZero(TOTAL_FLUX)>30000  then 'B112_01_008'
			 end) EVENT_FLUX,
		 */
		String sql = genBucketSql("event_flux", "toFloat64OrZero(TOTAL_FLUX)", "TOTAL_FLUX", tagListMap.get("event_flux"));
		sqlBuilder.append(sql);
	}
	
	/**
	 * 大网标签-月消费
	 * @param sqlBuilder
	 * @param tagMap
	 */
	public void appendEventConsume(StrBuilder sqlBuilder, Map<String, List<UserprofileTag>> tagListMap) {
		/**
		 * (case when toFloat32OrNull(MON_TOTAL_FEE)<10 then 'B112_02_001'
			when toFloat32OrNull(MON_TOTAL_FEE)>=10 and toFloat32OrNull(MON_TOTAL_FEE)<20 then 'B112_02_002'
			when  toFloat32OrNull(MON_TOTAL_FEE)>=20 and toFloat32OrNull(MON_TOTAL_FEE)<60  then 'B112_02_003'
			when  toFloat32OrNull(MON_TOTAL_FEE)>=60 and toFloat32OrNull(MON_TOTAL_FEE)<100  then 'B112_02_004'
			when  toFloat32OrNull(MON_TOTAL_FEE)>=100 and toFloat32OrNull(MON_TOTAL_FEE)<150  then 'B112_02_005'
			when  toFloat32OrNull(MON_TOTAL_FEE)>=150 and toFloat32OrNull(MON_TOTAL_FEE)<300  then 'B112_02_006'
			when  toFloat32OrNull(MON_TOTAL_FEE)>=300  then 'B112_02_007'
			else 'B112_02_008' end) EVENT_CONSUM,
		 */
		String sql = genBucketSql("event_consum", "toFloat32OrNull(MON_TOTAL_FEE)", "toFloat32OrNull(MON_TOTAL_FEE)", tagListMap.get("event_consum"));
		sqlBuilder.append(sql);
	}

	/**
	 * 大网标签-视频流量消耗
	 * @param sqlBuilder
	 * @param tagMap
	 */
	public void appendTotalFluxVideo(StrBuilder sqlBuilder, Map<String, List<UserprofileTag>> tagListMap) {
		/**
		 * (case when  toFloat64OrZero(TOTAL_FLUX_VIDEO)<=0  then 'B112_07_001'
			when  toFloat64OrZero(TOTAL_FLUX_VIDEO)>0 and toFloat64OrZero(TOTAL_FLUX_VIDEO)<=512 then 'B112_07_002'
			when   toFloat64OrZero(TOTAL_FLUX_VIDEO)>512 and toFloat64OrZero(TOTAL_FLUX_VIDEO)<=2096  then 'B112_07_003'
			when   toFloat64OrZero(TOTAL_FLUX_VIDEO)>2096 and toFloat64OrZero(TOTAL_FLUX_VIDEO)<=5120  then 'B112_07_004'
			when   toFloat64OrZero(TOTAL_FLUX_VIDEO)>5120 and toFloat64OrZero(TOTAL_FLUX_VIDEO)<=10240  then 'B112_07_005'
			when   toFloat64OrZero(TOTAL_FLUX_VIDEO)>10240 and toFloat64OrZero(TOTAL_FLUX_VIDEO)<=15720  then 'B112_07_006'
			when   toFloat64OrZero(TOTAL_FLUX_VIDEO)>15720 and toFloat64OrZero(TOTAL_FLUX_VIDEO)<=31480  then 'B112_07_007'
			when   toFloat64OrZero(TOTAL_FLUX_VIDEO)>31480  then 'B112_07_008'
 			end) EVENT_VIDEO_FLUX,
		 */
		String sql = genBucketSql("event_video_flux", "toFloat64OrZero(TOTAL_FLUX_VIDEO)", "toFloat64OrZero(TOTAL_FLUX_VIDEO)*0.001", 
				tagListMap.get("event_video_flux"));
		sqlBuilder.append(sql);
	}
	
	/**
	 * 大网标签-是否出账
	 * @param sqlBuilder
	 * @param tagMap
	 */
	public void appendEventIsAcct(StrBuilder sqlBuilder, Map<String, List<UserprofileTag>> tagListMap) {
		/**
		 * (case when IS_ACCT='1' then 'B112_14_002'
			when  IS_ACCT='0' then 'B112_14_003'
			else 'B112_14_001' end) EVENT_IS_ACCT,
		 */
		String sql = genBucketSql("event_is_acct", "IS_ACCT", "IS_ACCT", tagListMap.get("event_is_acct"));
		sqlBuilder.append(sql);
	}
	
	/**
	 * StringBuilder sqlBuilder
	 * @param sqlBuilder
	 */
	public void appendEventCancelProd(StrBuilder sqlBuilder) {
		sqlBuilder.appendLn("['B112_09_002'] as `EVENT_CANCEL_PROD.E`,")
				  .appendLn("['订购产品用户'] as `EVENT_CANCEL_PROD.C`,")
				  .append("['dg'] as `EVENT_CANCEL_PROD.V`");
	}
	
	/**
	 * 需要开启分批次生成逻辑
	 */
	@Override
	public boolean executeInBatchs() {
		return true;
	}

	@Override
	public long calcMobileRangeStep() {
		return _STEP;
	}
}
