<template>
	<el-dialog
		:visible.sync="isOpenComputed"
		:close-on-click-modal="false"
		:modal-append-to-body="false"
		@close="cancelHandle"
		custom-class="computed-dialog fit-screen-dialog"
		center
		top="6vh"
		v-dialogDrag
	>
		<div slot="title" style="display: flex; align-items: center">
			<img
				:src="$icons.computed"
				style="color: #fff; width: 16px; height: 16px; margin-right: 5px"
			/>
			<span style="font-size: 16px">{{ title }}</span>
		</div>
		<div class="dialog-main">
			<ul class="add-cont">
				<li class="add-li" v-for="(list, index) in addList" :key="index">
					<span class="li-tag">{{ list.tag }}</span>
					<el-select
						v-model="list.target"
						v-loadMore="searchLoad"
						:filterable="!list.target"
						clearable
						placeholder="请输入指标名称"
						style="width: 400px"
						@change="chooseTarget"
						@clear="clearHandle(index)"
						:disabled="calulateForm.view"
						remote
						:remote-method="searchTarget"
						@click.native="inputFocusHandle"
					>
						<i slot="prefix" class="el-input__icon el-icon-search"></i>
						<el-option
							v-for="item in searchOptions"
							:key="item.EdbInfoId"
							:label="$parent.currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
							:value="item.EdbInfoId"
						>
							<edbDetailPopover :info="item">
								<div slot="reference">{{$parent.currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName}}</div>
							</edbDetailPopover>
						</el-option>
					</el-select>

					<i class="el-icon-tickets" style="color:#409EFF;font-size:18px" @click="$emit('lookHistory',list.target)" v-if="list.target"/>
					
					<i
						class="el-icon-error del-tag"
						v-if="index > 3 && !calulateForm.view"
						@click="delTarget(index)"
					/>
					<span :class="{
						'target-date': true,
						'newest': list.end_date===newestDate
					}" v-if="list.start_date">{{
						`${list.start_date}至${list.end_date}`
					}}</span>
				</li>
			</ul>
			<span class="add-icon" @click="addTargetHandle" v-if="!calulateForm.view">
				<i
					class="el-icon-circle-plus-outline"
					style="color: #5882ef; font-size: 16px"
				/>
				添加更多参数
			</span>
			<div class="computed-min">
				<div class="computed-section">
					<div>
						<label class="label">空值处理
							<el-tooltip placement="top">
								<div slot="content" v-html="formTips['null-val']" style="width:300px;line-height:20px;"/>
								<i class="el-icon-question"/>
							</el-tooltip>
						</label>
						<el-select
							v-model="nullValueForm.nullValueWay"
							placeholder="请选择"
							:disabled="calulateForm.view"
						>
							<el-option
								v-for="item in nullWayOptions"
								:key="item.value"
								:label="item.label"
								:value="item.value"
							>
							</el-option>
						</el-select>
					</div>

					<div style="margin-left: 120px" v-if="showMaxNullDeal">
						<label class="label">MAX、MIN空值处理
							<el-tooltip placement="top">
								<div slot="content" v-html="formTips['max-null-val']" style="width:300px;line-height:20px;"/>
								<i class="el-icon-question"/>
							</el-tooltip>
						</label>
						<el-select
							v-model="nullValueForm.maxNullWay"
							placeholder="请选择"
							:disabled="calulateForm.view"
						>
							<el-option label="等于0" :value="1" />
							<el-option label="跳过空值" :value="2" />
						</el-select>
					</div>
				</div>	
				<div class="computed-section">
					<label class="label">计算公式
						<el-tooltip placement="top">
							<div slot="content" v-html="formTips['formula']" style="width:300px;line-height:20px;"/>
							<i class="el-icon-question"/>
						</el-tooltip>
					</label>
					<!-- <el-input placeholder="请输入公式" v-model="formula" clearable :disabled="calulateForm.view">
					</el-input> -->
					<ul class="formula-list">
						<li style="margin-bottom: 15px;">
							<el-input placeholder="请输入公式" v-model="formulaList[0].formula" clearable :disabled="calulateForm.view" style="width: 220px"/>
							
							<span v-if="formulaDateArr.length" class="date-section-text">{{formulaDateArr[formulaDateArr.length-1]}}(含)之后</span>

							<span class="example-txt">公式示例：A*0.5+B*C*1.2+120-MAX(A,B,C) &nbsp;函数支持：MAX(),MIN(),ln(A),log(a,A),abs(),exp(),pow(),round()</span>
						</li>

						<li class="formula-item" v-for="(item,index) in formulaList.slice(1)" :key="index+1">
							<el-input 
								placeholder="请输入公式" 
								v-model="item.formula" 
								clearable 
								:disabled="calulateForm.view"
								style="width: 220px"
							/>

							<el-date-picker
								v-model="item.date"
								type="date"
								value-format="yyyy-MM-dd"
								style="margin: 0 10px;width: 220px"
								placeholder="选择日期"
								:disabled="calulateForm.view"
								@change="selectFormulaDate($event,item)"
							/>

							<i class="el-icon-circle-close" style="font-size:20px;" v-if="!calulateForm.view" @click="removeFormulaItem(index+1)"/>

							<template v-if="formulaDateArr.length&&item.date">
								<span v-if="item.date===formulaDateArr[0]" class="date-section-text">{{formulaDateArr[0]}}之前</span>
								<span v-else class="date-section-text">{{formulaDateArr[formulaDateArr.findIndex(_ =>_ ===item.date)-1]}}(含)——{{item.date}}</span>
							</template>
						</li>
					</ul>
				</div>
				<el-button 
					v-if="!calulateForm.view" 
					icon="el-icon-plus" 
					style="margin-left:70px;" 
					@click="addFormulaHandle"
				>新增分段</el-button>

			</div>
			<el-form
				ref="diaForm"
				label-position="right"
				inline
				label-width="80px"
				:model="formData"
				:rules="formRules"
				:disabled="calulateForm.view"
			>
				<el-form-item label="指标名称" prop="targetName">
					<el-input
						v-model="formData.targetName"
						style="width: 340px"
						placeholder="请输入指标名称"
					/>
				</el-form-item>
				<el-form-item label="单位" prop="unit">
					<selectUnit v-model="formData.unit" style="width: 340px" />
				</el-form-item>
				<el-form-item label="指标目录" prop="menu">
					<el-cascader
						v-model="formData.menu"
						:options="options"
						:props="levelProps"
						clearable
						placeholder="请选择指标目录"
					/>
				</el-form-item>
				<el-form-item label="频度" prop="frequency">
					<el-select
						v-model="formData.frequency"
						placeholder="请选择频率"
						style="width: 340px"
						clearable
					>
						<el-option
							v-for="item in frequencyArr"
							:key="item"
							:label="item"
							:value="item"
						>
						</el-option>
					</el-select>
				</el-form-item>
			</el-form>
		</div>
		<div class="dia-bot" v-if="!calulateForm.view">
			<el-button
				type="primary"
				style="margin-right: 20px"
				@click="saveHandle"
				:loading="dataloading"
				v-if="title==='计算指标'"
				>生成计算指标</el-button
			>
			<el-button
				type="primary"
				style="margin-right: 20px"
				@click="saveHandle"
				v-else
				>保存</el-button
			>
			<el-button type="primary" plain @click="cancelHandle('cancel')">取消</el-button>
		</div>
		<el-popover
			placement="top-start"
			width="360"
			trigger="click">
			<p style="padding:30px;line-height:25px;" v-html="$parent.tips.get(type)"/>
			<span slot="reference" class="tip-label">公式说明</span>
		</el-popover>
	</el-dialog>
</template>

<script>
import { dataBaseInterface } from '@/api/api.js';
import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
import { formRules } from '../databaseComponents/util';
import { unitArr } from '@/utils/defaultOptions';
const tag_arr = [];
for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
export default {
	name: '',
	props: {
		isOpenComputed: {
			type: Boolean,
		},
		title: {
			type: String,
			default: '计算指标',
		},
		calulateForm: {
			type: Object,
		},
		calulateList: {
			type: Array,
		},
		edbSource: { // ''||'predict'
			type: String,
			default: ''
		}
	},
	computed: {
		type() {
			return this.edbSource ? 31 : 4;
		},

		/* max空值处理显示 当输入的公式包含MAX、MIN且空值处理为0时，输入公式失焦后出现右侧选项； */
		showMaxNullDeal() {
			let haveMaxOrMin = this.formulaList.some(_ => _.formula.toUpperCase().includes('MAX') || _.formula.toUpperCase().includes('MIN'))

			return haveMaxOrMin && this.nullValueForm.nullValueWay===4
		},

		formulaDateArr() {
			return this.formulaList.map(_ => _.date).filter(_ => _).sort((a,b) => new Date(a)-new Date(b))
		}
	},
	watch: {
		isOpenComputed(newval) {
			newval && this.getMenu();
			// newval && this.searchTarget('');
			/* 回显 */
			if (this.calulateList.length && newval) {
				this.addList = _.cloneDeep(this.calulateList);
				this.formulaList = JSON.parse(this.calulateForm.formula).map(_ => ({
					formula: _.f,
					date: _.d||''
				}));
				this.formData = {
					targetName: this.calulateForm.targetName,
					unit: this.calulateForm.unit,
					menu: this.calulateForm.menu,
					frequency: this.calulateForm.frequency,
				};

				this.nullValueForm = {
					nullValueWay: this.calulateForm.emptyType,
					maxNullWay: this.calulateForm.maxEmptyType,
				}

				this.searchOptions = this.calulateList.map(item => ({
					EdbInfoId: item.target,
					EdbName: item.edb_name,
				}))

				this.getNewestDate();
			}
		},
	},
	data() {
		return {
			options: [],
			levelProps: {
				label: 'ClassifyName',
				value: 'ClassifyId',
				children: 'Children',
				checkStrictly: true
			},
			frequencyArr: ['日度', '周度','旬度','月度', '季度', '年度'],
			formRules,
			unitArr,
			addList: [
				{
					tag: tag_arr[0],
					target: '',
					start_date: '',
					end_date: '',
				},
				{
					tag: tag_arr[1],
					target: '',
					start_date: '',
					end_date: '',
				},
				{
					tag: tag_arr[2],
					target: '',
					start_date: '',
					end_date: '',
				},
				{
					tag: tag_arr[3],
					target: '',
					start_date: '',
					end_date: '',
				},
			],
			searchOptions: [],
			formula: '', //计算公式
			formulaList: [ //公式数组
				{ formula: '', }
			],
			dataloading: false,
			formData: {
				targetName: '',
				unit: '',
				menu: '',
				frequency: '',
			},
			search_have_more: false,
			search_page: 1,
			current_search:'',

			newestDate: '',

			nullValueForm: {
				nullValueWay: 0,
				maxNullWay: 1
			},//空值处理
			nullWayOptions: [
				{ label: '查找前后35天最近值',value: 0 },
				{ label: '不计算',value: 1 },
				{ label: '前值填充',value: 2 },
				{ label: '后值填充',value: 3 },
				{ label: '等于0',value: 4 },
			],
			formTips: {
				'null-val': `1、查找前后35天最近值：在参与计算的日期序列上某指标无值时，该指标往前/往后找距离最近的值作为当天的值进行计算，遍历允许跨年，往前最多35天，往后最多35天<br>
				2、不计算：只要有一个指标在某个日期没有值(即空值)，则计算指标在该日期没有值 <br>
				3、前值填充：空值优先以最近的前值填充，没有前值时，用后值填充 <br>
				4、后值填充：空值优先以最近的后值填充，没有前值时，用后值填充 <br>
				5、等于0：空值以0值参与计算 <br>
				注意：此处缺失值的处理，作用于数据全部时间段`,
				'max-null-val': `MAX、MIN公式中指标存在空值时按如下规则处理：<br>
				1、等于0，空值用0参与计算；<br>
				2、跳过空值，去除空值指标，剩余指标进行计算，若该日期所有指标均为空值，则该日期无值；`,
				'formula':`1、支持新增分段，实现不同分段使用不同的计算公式，若未新增分段，则所有日期序列用统一公式计算<br>
				2、新增分段需配置新公式和时间节点，在时间节点之前（不含）使用新公式，在时间节点之后（含）使用已配置公式，每个分段公式支持修改<br>
				3、分段时间节点不允许重复，不允许超出第一个指标的日期区间`
			}

		};
	},
	methods: {
		/* 获取目录结构 */
		async getMenu() {
			const res = this.edbSource === 'predict'
				? await preDictEdbInterface.classifyListV2()
				: await dataBaseInterface.menuListV3()
				if (res.Ret !== 200) return
				
				this.filterNodes(res.Data.AllNodes||[]);
				this.options = res.Data.AllNodes || [];
		},
		// 递归改变第三级目录结构
		filterNodes(arr) {
			arr.length &&
				arr.forEach((item) => {
					item.Children.length && this.filterNodes(item.Children);
					if (!item.Children.length) {
						delete item.Children;
					}
				});
		},
		/* 添加额外的指标列 */
		addTargetHandle() {
			if(this.addList.length >= 26) return this.$message.warning('添加指标个数已达上限')
			let tag = this.addList[this.addList.length-1].tag;
			let index = tag_arr.findIndex(item => item === tag);
			const item = {
				tag: tag_arr[index+1],
				target: '',
				start_date: '',
				end_date: ''
			};
			this.addList.push(item);
		},
		/* 搜索指标 */
		searchTarget(query) {
			this.search_page = 1;
			this.current_search = query;
			this.searchApi(this.current_search);
		},

		/* 聚焦获取当前检索 */
		inputFocusHandle(e) {
			this.search_page = 1;
			this.current_search = e.target.value;
			this.searchApi(this.current_search);
		},

		async searchApi(query,page=1) {
			const res = this.edbSource === 'predict'
				? await preDictEdbInterface.edbSearch({
            Keyword: query,
            CurrentIndex: page,
						FilterSource: this.type === 45 ? 3 : this.type === 66 ? 6 : 1,
						Frequency: this.type===64?'季度': ''
          })
				: await dataBaseInterface.targetSearchByPage({
					KeyWord:query,
					CurrentIndex: page,
					FilterSource: this.type === 14 ? 3 : this.type === 63 ? 6 : 1,
					Frequency: this.type===61?'季度': ''
				})
				if(res.Ret !== 200) return

				const { List,Paging } = res.Data;
				this.search_have_more = page < Paging.Pages;
				this.searchOptions = page === 1 ? List : this.searchOptions.concat(List);
		},

		searchLoad() {
			if(!this.search_have_more) return;
			this.searchApi(this.current_search,++this.search_page)
		},

		/* 选中指标 显示开始日期结束日期 */
		chooseTarget(val) {
			if (val) {
				const choose_obj = this.searchOptions.find(
					(item) => item.EdbInfoId === val
				);
				this.addList.forEach((list) => {
					if (list.target === val) {
						list.start_date = choose_obj.StartDate;
						list.end_date = choose_obj.EndDate;
						this.getNewestDate();
					}
				});
			}
		},

		/* 获取所选日期最早日期 */
		getNewestDate() {
			let dateArr = this.addList.filter(_ => _.end_date).map(_ => new Date(_.end_date).getTime())
			let earliestDate = Math.min(...dateArr);
			let sameDateArr = dateArr.filter(_ => _===earliestDate)
			if(dateArr.length === 1 || sameDateArr.length===dateArr.length) {
				this.newestDate = '';
				return
			}
			this.newestDate = this.$moment(Math.min(...dateArr)).format('YYYY-MM-DD');
		},	

		/* 清空指标和关联日期 */
		clearHandle(index) {
			this.addList[index].start_date = '';
			this.addList[index].end_date = '';
			this.getNewestDate();
		},
		// 删除指标
		delTarget(index) {
			this.addList.splice(index, 1);
			this.getNewestDate();
		},
		async saveHandle() {
				if (!this.formulaList[0].formula) return this.$message.warning('计算公式不能为空');
				await this.$refs.diaForm.validate();

				// 指标id数组
				let EdbInfoIdArr = this.addList.filter((item) => item.target).map((item) => ({
						EdbInfoId: item.target,
						FromTag: item.tag,
					}));

				let formulaArr = this.formulaList
					.filter((_,index) => index===0||(index>0&&_.formula&&_.date))
					.map(_ => ({f: _.formula,d: _.date}))

				const { nullValueWay,maxNullWay } = this.nullValueForm;
				
				let params = {
					CalculateFormula: JSON.stringify(formulaArr),
					ClassifyId: this.formData.menu[this.formData.menu.length - 1] || 0,
					EdbName: this.formData.targetName,
					Frequency: this.formData.frequency,
					Unit: this.formData.unit,
					EdbInfoIdArr,
					EmptyType: nullValueWay,
					MaxEmptyType: maxNullWay
				};
				this.dataloading = true;

				let res;
				if(this.edbSource === 'predict') {
					res = await preDictEdbInterface.calculateEdbSave(this.calulateForm.edb_id ? {...params,EdbInfoId:this.calulateForm.edb_id } : params)
				}else {
					res = this.calulateForm.edb_id
						? await dataBaseInterface.calculateEdit({...params,EdbInfoId: this.calulateForm.edb_id})
						: await dataBaseInterface.calculateAdd(params)
				}

				this.dataloading = false;
				if (res.Ret !== 200) return
				this.$message.success(res.Msg);
				this.calulateForm.edb_id 
						? this.$emit('addCallBack','edit') 
						: this.$emit('addCallBack','add',{ code:res.Data.UniqueCode,id:res.Data.EdbInfoId,classifyId:params.ClassifyId });
				this.init();
		},

		/* 新增公式分段 */
		addFormulaHandle() {
			let addItem = {
				formula: this.formulaList[this.formulaList.length-1].formula,
				date: ''
			}
			this.formulaList.push(addItem)
		},

		/* 移除公式 */
		removeFormulaItem(index) {
			this.formulaList.splice(index,1)
		},

		/* 选择日期 检验排 */
		selectFormulaDate(val,item) {
			console.log(val,item)
			const { start_date,end_date } = this.addList[0];

			if(!start_date) return

			let dateStamp = new Date(val).getTime(), 
					startStamp = new Date(start_date).getTime(),
					endStamp = new Date(end_date).getTime();
			if (dateStamp > endStamp || dateStamp < startStamp) {
				item.date = '';
				return this.$message.warning('分段日期必须在第一个指标日期区间')
			}

			else if(this.formulaList.filter(_ => _.date===val).length>1) {
				item.date = '';
				return this.$message.warning('分段日期不可重复')
			}
		},

		init() {
			this.$refs.diaForm.resetFields();
			this.addList = [
				{
					tag: tag_arr[0],
					target: '',
					start_date: '',
					end_date: '',
				},
				{
					tag: tag_arr[1],
					target: '',
					start_date: '',
					end_date: '',
				},
				{
					tag: tag_arr[2],
					target: '',
					start_date: '',
					end_date: '',
				},
				{
					tag: tag_arr[3],
					target: '',
					start_date: '',
					end_date: '',
				},
			];
			this.searchOptions = [];
			this.formula = '';
			this.formData = {
				targetName: '',
				unit: '',
				menu: '',
				frequency: '',
			};
			this.formulaList = [
				{ formula: '' }
			]
			this.nullValueForm = {
				nullValueWay: 0,
				maxNullWay: 1
			}

		},
		cancelHandle(type) {
			this.init();
			this.$emit('cancel');
			type==='cancel' && !this.calulateForm.edb_id && this.$emit('openPrev');
		},
	},
	mounted() {},
};
</script>
<style lang="scss">
.computed-dialog {
    max-width: 1200px !important;
    width:85vw;
	overflow: hidden;
	div::-webkit-scrollbar {
		width: 6px !important;
	}
	.el-dialog__body {
		max-height: 700px;
		overflow: auto;
	}
	.dialog-main {
		padding: 25px 42px 25px 25px;
		@media screen and (max-height:850px){
			box-sizing: border-box;
			height: 65vh;
			overflow-y: auto;
		}
		.el-cascader .el-input {
			width: 340px;
		}
		.add-cont {
			display: flex;
			flex-wrap: wrap;
			justify-content: space-between;
			.add-li {
				position: relative;
				margin-bottom: 48px;
				.li-tag {
					font-size: 16px;
					margin-right: 8px;
				}
				.del-tag {
					position: absolute;
					right: -30px;
					top: 12px;
					font-size: 16px;
					cursor: pointer;
				}
				.target-date {
					color: #5882ef;
					position: absolute;
					bottom: -25px;
					left: 24px;
					&.newest {
						color: #f00;
					}
				}
			}
		}
		.add-icon {
			font-size: 16px;
			color: #5882ef;
			cursor: pointer;
		}
		.computed-min {
			margin: 50px 0;
			padding-bottom: 40px;
			border-bottom: 1px dashed #aab4cc;
			.computed-section {
				display: flex;
				margin-top: 20px;
			}
			.label {
				padding:10px 10px 10px 0;
			}
			.example-txt {
				display: block;
				margin-top: 10px;
			}
			.formula-item {
				display: flex;
				align-items: center;
				margin-bottom: 15px;
			}
			.date-section-text {
				margin-left: 15px;
			}
		}
	}
	.dia-bot {
		padding-bottom: 40px;
		display: flex;
		justify-content: center;
	}
	.tip-label {
		position: absolute;
		bottom: 30px;
		right: 30px;
		color: #409EFF;
		cursor: pointer;
	}
}
</style>
