<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
	<th:block th:include="include :: header(#{ivr.add.title})" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
	<form class="form-horizontal m" id="form-ivr-add" th:object="${ccIvr}">
		<input name="id" th:field="*{id}" type="hidden">
		<input id="rootId" name="rootId" th:field="*{rootId}" type="hidden">
		<input id="ttsTextWav" name="ttsTextWav" th:field="*{ttsTextWav}" type="hidden">
		<input id="pressKeyInvalidTipsWav" name="pressKeyInvalidTipsWav" th:field="*{pressKeyInvalidTipsWav}" type="hidden">
		<input id="hangupTipsWav" name="hangupTipsWav" th:field="*{hangupTipsWav}" type="hidden">
		<input id="parentNodeId" name="parentNodeId" type="hidden" th:field="*{parentNodeId}" />
		<div class="form-group">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.digit}"></label>
			<div class="col-sm-8">
				<select id="digit" name="digit" th:field="*{digit}" class="form-control m-b">
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
					<option value="4">4</option>
					<option value="5">5</option>
					<option value="6">6</option>
					<option value="7">7</option>
					<option value="8">8</option>
					<option value="9">9</option>
					<option value="0">0</option>
				</select>
			</div>
		</div>
		<div class="form-group">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.ivrNodeName}"></label>
			<div class="col-sm-8">
				<input class="form-control" type="text" name="ivrNodeName" th:field="*{ivrNodeName}" required>
			</div>
		</div>

		<div class="col-xs-12">
			<div class="form-group">
				<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.ttsProvider}"></label>
				<div class="col-sm-8">
					<select name="ttsProvider" class="form-control" id="ttsProviderSelect" th:field="*{ttsProvider}" required>
						<option value="" th:text="#{ivr.form.ttsProvider.empty}"></option>
					</select>
				</div>
			</div>
		</div>

		<!-- 新增：TTS语言选择 -->
		<div class="col-xs-12" id="ttsLanguageCodeDiv" style="display:none;">
			<div class="form-group">
				<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.ttsLanguageCode}">TTS语言</label>
				<div class="col-sm-8">
					<select name="ttsLanguageCode" id="ttsLanguageCode" th:field="*{ttsLanguageCode}" class="form-control" required>
						<option value="" th:text="#{ivr.form.ttsLanguageCode.empty}">请选择TTS语言</option>
					</select>
				</div>
			</div>
		</div>

		<!-- 新增：TTS模型选择 -->
		<div class="col-xs-12" id="ttsModelsDiv" style="display:none;">
			<div class="form-group">
				<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.ttsModels}">TTS模型</label>
				<div class="col-sm-8">
					<select name="ttsModels" id="ttsModels" th:field="*{ttsModels}" class="form-control" required>
						<option value="" th:text="#{ivr.form.ttsModels.empty}">请选择TTS模型</option>
					</select>
				</div>
			</div>
		</div>

		<div class="col-xs-12">
			<div class="form-group">
				<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.voiceCode}"></label>
				<div class="col-sm-8">
					<select name="voiceCode" id="voiceCode" class="form-control" th:field="*{voiceCode}" required>
						<option value="" th:text="#{ivr.form.voiceCode.empty}" ></option>
					</select>
				</div>
			</div>
		</div>

		<!-- ttsText 输入组 -->
		<div class="form-group">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.ttsText}"></label>
			<div class="col-sm-8">
				<div class="input-group">
					<textarea class="form-control" name="ttsText" id="ttsText" th:field="*{ttsText}" th:placeholder="#{ivr.form.placeholder.ttsText}" rows="3" required></textarea>
					<span class="input-group-btn">
                <!-- 新增的合成按钮 -->
                <button type="button" class="btn btn-success btn-tts-synthesize" data-field="ttsText" th:title="#{ivr.form.btn.title.tts}">
                    <i class="fa fa-magic"></i> <span th:text="#{ivr.form.btn.tts}"></span>
                </button>
						<!-- 原有的上传按钮 -->
                <button type="button" class="btn btn-info btn-file-upload" data-field="ttsText" data-upload-type="voice" th:title="#{ivr.form.btn.title.upload}">
                    <i class="fa fa-upload"></i> <span th:text="#{ivr.form.btn.upload}"></span>
                </button>
            </span>
				</div>
				<span class="help-block m-b-none" th:text="#{ivr.form.tips.helpblock}"></span>
			</div>
		</div>

		<div class="form-group" id="ttsAudioPreview" style="display:none;">
			<label class="col-sm-3 control-label" th:text="#{ivr.form.title.ttsAudioPreview}"></label>
			<div class="col-sm-8">
				<audio controls class="form-control" style="height: 40px;">
					<source src="" type="audio/wav">
					<span th:text="#{ivr.form.audio.notSupported}"></span>
				</audio>
			</div>
		</div>

		<div class="form-group">
			<label class="col-sm-3 control-label" th:text="#{ivr.form.action}"></label>
			<div class="col-sm-8">
				<select id="action" name="action" th:field="*{action}" class="form-control m-b">
					<option value="play" th:text="#{ivr.form.action.play}"></option>
					<option value="acd" th:text="#{ivr.form.action.acd}"></option>
					<option value="extension" th:text="#{ivr.form.action.extension}"></option>
					<option value="gateway" th:text="#{ivr.form.action.gateway}"></option>
					<option value="hangup" th:text="#{ivr.form.action.hangup}"></option>
					<option value="playAndGetDigits" th:text="#{ivr.form.action.playAndGetDigits}"></option>
					<option value="ai" th:text="#{ivr.form.action.ai}"></option>
				</select>
			</div>
		</div>

		<div class="col-xs-12 transfer-field acd-transfer" style="display: none;">
			<div class="form-group" >
				<label class="col-sm-3 control-label " th:text="#{ivr.form.aiTransferGroupId}"></label>
				<div class="col-sm-8">
					<select name="aiTransferGroupId" th:field="*{aiTransferGroupId}" class="form-control">
						<option value="" th:text="#{ivr.form.aiTransferGroupId.empty}"></option>
					</select>
				</div>
			</div>
		</div>

		<div class="col-xs-12 transfer-field gateway-transfer" style="display: none;">
			<div class="form-group" >
				<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.aiTransferGatewayId}"></label>
				<div class="col-sm-8">
					<select name="aiTransferGatewayId" th:field="*{aiTransferGatewayId}" class="form-control" required>
						<option value="" th:text="#{ivr.form.aiTransferGatewayId.empty}"></option>
					</select>
				</div>
			</div>
		</div>
		<div class="col-xs-12 transfer-field gateway-transfer" style="display: none;">
			<div class="form-group" >
				<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.aiTransferGatewayDestNumber}"></label>
				<div class="col-sm-8">
					<input name="aiTransferGatewayDestNumber" th:field="*{aiTransferGatewayDestNumber}" class="form-control" type="text" required>
				</div>
			</div>
		</div>
		<div class="col-xs-12 transfer-field extension-transfer" style="display: none;">
			<div class="form-group" >
				<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.aiTransferExtNumber}"></label>
				<div class="col-sm-8">
					<input name="aiTransferExtNumber" th:field="*{aiTransferExtNumber}" class="form-control" type="text" required>
				</div>
			</div>
		</div>

		<div class="form-group transfer-field ivr-transfer" style="display: none;">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.userInputVarName}"></label>
			<div class="col-sm-8">
				<input class="form-control" type="text" name="userInputVarName" id="userInputVarName" th:field="*{userInputVarName}" required>
			</div>
		</div>

		<div class="col-xs-12 transfer-field ai-transfer" style="display: none;">
			<div class="form-group" >
				<label class="col-sm-3 control-label " th:text="#{ivr.form.aiInboundId}"></label>
				<div class="col-sm-8">
					<select name="aiInboundId" th:field="*{aiInboundId}" class="form-control">
						<option value="" th:text="#{ivr.form.aiInboundId.empty}"></option>
					</select>
				</div>
			</div>
		</div>

		<!-- hangupTips 输入组 -->
		<div class="form-group">
			<label class="col-sm-3 control-label" th:text="#{ivr.form.hangupTips}"></label>
			<div class="col-sm-8">
				<div class="input-group">
					<textarea class="form-control" name="hangupTips" id="hangupTips" th:field="*{hangupTips}" th:placeholder="#{ivr.form.placeholder.hangupTips}" rows="3"></textarea>
					<span class="input-group-btn">
                <!-- 新增的合成按钮 -->
                <button type="button" class="btn btn-success btn-tts-synthesize" data-field="hangupTips" th:title="#{ivr.form.btn.title.tts}">
                    <i class="fa fa-magic"></i> <span th:text="#{ivr.form.btn.tts}"></span>
                </button>
						<!-- 原有的上传按钮 -->
                <button type="button" class="btn btn-info btn-file-upload" data-field="hangupTips" data-upload-type="voice" th:title="#{ivr.form.btn.title.upload}">
                    <i class="fa fa-upload"></i> <span th:text="#{ivr.form.btn.upload}"></span>
                </button>
            </span>
				</div>
				<span class="help-block m-b-none" th:text="#{ivr.form.tips.helpblock}"></span>
			</div>
		</div>

		<div class="form-group" id="hangupTipsAudioPreview" style="display:none;">
			<label class="col-sm-3 control-label" th:text="#{ivr.form.title.ttsAudioPreview}"></label>
			<div class="col-sm-8">
				<audio controls class="form-control" style="height: 40px;">
					<source src="" type="audio/wav">
					<span th:text="#{ivr.form.audio.notSupported}"></span>
				</audio>
			</div>
		</div>

		<div class="form-group">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.waitKeyTimeout}"></label>
			<div class="col-sm-8">
				<input class="form-control" type="number" name="waitKeyTimeout" id="waitKeyTimeout" th:field="*{waitKeyTimeout}" min="5" step="1" required>
			</div>
		</div>

		<div class="form-group">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.maxPressKeyFailures}"></label>
			<div class="col-sm-8">
				<input class="form-control" type="number" name="maxPressKeyFailures" id="maxPressKeyFailures" th:field="*{maxPressKeyFailures}" min="1" step="1" required>
			</div>
		</div>

		<!-- pressKeyInvalidTips 输入组 -->
		<div class="form-group">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.pressKeyInvalidTips}"></label>
			<div class="col-sm-8">
				<div class="input-group">
					<textarea class="form-control" name="pressKeyInvalidTips" id="pressKeyInvalidTips" th:field="*{pressKeyInvalidTips}" th:placeholder="#{ivr.form.placeholder.pressKeyInvalidTips}" rows="3" required></textarea>
					<span class="input-group-btn">
                <!-- 新增的合成按钮 -->
                <button type="button" class="btn btn-success btn-tts-synthesize" data-field="pressKeyInvalidTips" th:title="#{ivr.form.btn.title.tts}">
                    <i class="fa fa-magic"></i> <span th:text="#{ivr.form.btn.tts}"></span>
                </button>
						<!-- 原有的上传按钮 -->
                <button type="button" class="btn btn-info btn-file-upload" data-field="pressKeyInvalidTips" data-upload-type="voice" th:title="#{ivr.form.btn.title.upload}">
                    <i class="fa fa-upload"></i> <span th:text="#{ivr.form.btn.upload}"></span>
                </button>
            </span>
				</div>
				<span class="help-block m-b-none" th:text="#{ivr.form.tips.helpblock}"></span>
			</div>
		</div>

		<div class="form-group" id="invalidTipsAudioPreview" style="display:none;">
			<label class="col-sm-3 control-label" th:text="#{ivr.form.title.ttsAudioPreview}"></label>
			<div class="col-sm-8">
				<audio controls class="form-control" style="height: 40px;">
					<source src="" type="audio/wav">
					<span th:text="#{ivr.form.audio.notSupported}"></span>
				</audio>
			</div>
		</div>

		<div class="form-group">
			<label class="col-sm-3 control-label" th:text="#{ivr.form.failedAction}"></label>
			<div class="col-sm-8">
				<select name="failedAction" th:field="*{failedAction}" class="form-control m-b">
					<option value="hangup" th:text="#{ivr.form.failedAction.hangup}"></option>
					<option value="upaction" th:text="#{ivr.form.failedAction.upaction}"></option>
				</select>
			</div>
		</div>

		<div class="form-group">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.digitRange}"></label>
			<div class="col-sm-8">
				<input class="form-control" type="text" name="digitRange" id="digitRange" th:field="*{digitRange}"
					   th:placeholder="#{ivr.form.placeholder.digitRange}" required>
				<span class="help-block m-b-none" th:text="#{ivr.form.tips.digitRange}"></span>
			</div>
		</div>

		<div class="form-group length-field">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.maxLen}"></label>
			<div class="col-sm-8">
				<input class="form-control" type="text" name="maxLen" id="maxLen" th:field="*{maxLen}" required>
			</div>
		</div>

		<div class="form-group length-field">
			<label class="col-sm-3 control-label is-required" th:text="#{ivr.form.minLen}"></label>
			<div class="col-sm-8">
				<input class="form-control" type="text" name="minLen" id="minLen" th:field="*{minLen}" required>
			</div>
		</div>

		<div class="form-group">
			<label class="col-sm-3 control-label" th:text="#{ivr.form.enabled}"></label>
			<div class="col-sm-8">
				<select id="enabled" name="enabled" th:field="*{enabled}" class="form-control m-b">
					<option value="1" th:text="#{ivr.form.enabled1}"></option>
					<option value="0" th:text="#{ivr.form.enabled0}"></option>
				</select>
			</div>
		</div>
	</form>
</div>

<!-- 变量选择模态框 -->
<div id="variableSelector" style="display: none; position: absolute; z-index: 9999;
     background: white; border-radius: 4px; box-shadow: 0 4px 12px rgba(0,0,0,0.15);
     width: 260px; max-height: 320px; overflow-y: auto;">
	<div style="background-color: #f5f5f5; padding: 6px 12px; border-bottom: 1px solid #ddd;">
		<strong style="font-size: 12px; color: #333;" th:text="#{ivr.variableSelector.title}"></strong>
		<small class="text-muted" style="float: right; margin-top: 2px;" th:text="#{ivr.variableSelector.tip}"></small>
	</div>
	<table class="table table-hover table-condensed" style="margin-bottom: 0; font-size: 12px;">
		<tbody id="variableList">
		<!-- 变量列表将通过JS动态填充 -->
		</tbody>
	</table>
</div>

<th:block th:include="include :: footer" />
<script th:inline="javascript">
	var prefix = ctx + "cc/ivr";

	// 可用变量列表（可扩展）
	var availableVariables = [];

	$(function() {
		// 设置digitRange默认值（纯数字正则）
		var $digitRange = $('#digitRange');
		if (!$digitRange.val().trim()) {
			$digitRange.val('^[0-9]$');
		}

		if (!$('#maxLen').val()) {
			$('#maxLen').val('1');
		}
		if (!$('#minLen').val()) {
			$('#minLen').val('1');
		}

		// 2. waitKeyTimeout为空时设为7
		if (!$('#waitKeyTimeout').val()) {
			$('#waitKeyTimeout').val('7');
		}

		// 3. maxPressKeyFailures为空时设为3
		if (!$('#maxPressKeyFailures').val()) {
			$('#maxPressKeyFailures').val('3');
		}

		// ========== 注册自定义校验方法 ==========

		// 1. 校验digit在同一层级是否重复（排除自身记录）
		$.validator.addMethod("checkDigit", function(value, element) {
			var parentNodeId = $('#parentNodeId').val();
			var currentId = /*[[${ccIvr.id}]]*/ '';

			if (parentNodeId === '0' || !value) {
				return true;
			}

			var isValid = false;
			$.ajax({
				url: ctx + "cc/ivr/checkDigit",
				type: "POST",
				async: false, // 必须同步
				data: {
					digit: value,
					parentNodeId: parentNodeId,
					id: currentId // 编辑时排除自身
				},
				dataType: "json",
				success: function(rsp) {
					isValid = (rsp.code === 0);
				},
				error: function() {
					isValid = false;
				}
			});
			return isValid;
		}, i18n("ivr.validator.msg.checkDigit"));

		// 2. 校验minLen <= maxLen
		$.validator.addMethod("minLenCheck", function(value, element) {
			var maxLen = $('#maxLen').val();
			if (value && maxLen) {
				return parseInt(value) <= parseInt(maxLen);
			}
			return true;
		}, i18n("ivr.validator.msg.minLenCheck"));

		// 3. 校验maxLen >= minLen
		$.validator.addMethod("maxLenCheck", function(value, element) {
			var minLen = $('#minLen').val();
			if (value && minLen) {
				return parseInt(value) >= parseInt(minLen);
			}
			return true;
		}, i18n("ivr.validator.msg.maxLenCheck"));

		// 4. 校验正则表达式有效性（空值时自动填充默认值）
		$.validator.addMethod("validRegex", function(value, element) {
			if (!value) {
				$(element).val('^[0-9]$');
				return true;
			}
			try {
				new RegExp(value);
				return true;
			} catch(e) {
				return false;
			}
		}, i18n("ivr.validator.msg.validRegex"));

		// ========== 初始化表单验证 ==========
		$("#form-ivr-add").validate({
			focusCleanup: true,
			ignore: ":hidden", // 忽略隐藏字段
			rules: {
				digit: {
					checkDigit: true
				},
				minLen: {
					minLenCheck: true
				},
				maxLen: {
					maxLenCheck: true
				},
				digitRange: {
					validRegex: true
				}
			},
			onfocusout: function(element) {
				$(element).valid();
			}
		});

		// minLen和maxLen联动校验
		$('#minLen, #maxLen').on('blur', function() {
			$('#minLen').valid();
			$('#maxLen').valid();
		});

		// 加载网关下拉框数据
		$.ajax({
			url: ctx + "cc/gateways/outbound",
			success: function(rsp) {
				var gatewaySelect = $('select[name="aiTransferGatewayId"]');
				gatewaySelect.empty();
				gatewaySelect.append('<option value="">' + i18n('ivr.form.aiTransferGatewayId.empty') + '</option>');
				rsp.data.forEach(function(gateway) {
					gatewaySelect.append($("<option>").attr("value", gateway.id).text(gateway.gwDesc));
				});
				// 回显已保存的aiTransferGatewayId
				var aiTransferGatewayId = /*[[${ccIvr.aiTransferGatewayId}]]*/ '';
				if (aiTransferGatewayId) {
					gatewaySelect.val(aiTransferGatewayId);
				}
			}
		});

		// 加载TTS提供商下拉框数据
		$.ajax({
			url: ctx + "aicall/ttsAliyun/tts/voiceSource/all",
			success: function(rsp) {
				var ttsProviderSelect = $('#ttsProviderSelect');
				ttsProviderSelect.empty();
				ttsProviderSelect.append('<option value="">' + i18n('ivr.form.ttsProvider.empty') + '</option>');
				// 遍历 map 对象，key 作为 value，value 作为显示文本
				Object.entries(rsp.data).forEach(function([key, value]) {
					ttsProviderSelect.append($("<option>").attr("value", key).text(value));
				});
				// 回显已保存的provider并加载对应语言和音色
				var ttsProvider = /*[[${ccIvr.ttsProvider}]]*/ '';
				if (ttsProvider) {
					ttsProviderSelect.val(ttsProvider);
					loadTtsLanguages(ttsProvider, function() {
						var savedTtsLanguageCode = /*[[${ccIvr.ttsLanguageCode}]]*/ '';
						if (savedTtsLanguageCode) {
							$('#ttsLanguageCode').val(savedTtsLanguageCode);
							loadTtsModels(ttsProvider, savedTtsLanguageCode, function() {
								var savedTtsModels = /*[[${ccIvr.ttsModels}]]*/ '';
								if (savedTtsModels) {
									$('#ttsModels').val(savedTtsModels);
								}
								// 确保在模型设置完成后再加载音色
								loadVoicesByVoiceSourceAndLanguage(ttsProvider, savedTtsLanguageCode, $('#ttsModels').val());
							});
						}
					});
				}
			}
		});

		// 加载业务组下拉框数据
		$.ajax({
			url: ctx + "cc/bizgroup/all",
			success: function(rsp) {
				var groupSelect = $('select[name="aiTransferGroupId"]');
				groupSelect.empty();
				groupSelect.append('<option value="">' + i18n('ivr.form.aiTransferGroupId.empty') + '</option>');
				rsp.data.forEach(function(bizGroup) {
					groupSelect.append($("<option>").attr("value", bizGroup.groupId).text(bizGroup.bizGroupName));
				});
				// 设置音色下拉框的选中项
				var groupId = /*[[${ccIvr.aiTransferGroupId}]]*/ '';
				if (groupId) {
					groupSelect.val(groupId);
				}
			}
		});


		// 加载ai客服配置下拉框数据
		$.ajax({
			url: ctx + "aicall/inboundllm/ai/all",
			success: function(rsp) {
				var aiInboundIdSelect = $('select[name="aiInboundId"]');
				aiInboundIdSelect.empty();
				aiInboundIdSelect.append('<option value="">' + i18n('ivr.form.aiInboundId.empty') + '</option>');
				rsp.data.forEach(function(aiInboundId) {
					aiInboundIdSelect.append($("<option>").attr("value", aiInboundId.id).text(aiInboundId.inboundAlias));
				});
				// 设置音色下拉框的选中项
				var aiInboundId = /*[[${ccIvr.aiInboundId}]]*/ '';
				if (aiInboundId) {
					aiInboundIdSelect.val(aiInboundId);
				}
			}
		});

		// 绑定文件上传按钮事件
		$(document).on('click', '.btn-file-upload', function() {
			var fieldId = $(this).data('field');
			var uploadType = $(this).data('upload-type') || 'voice';
			openUploadModal(fieldId, uploadType);
		});

		// 提供商变更事件
		$(document).on('change', '#ttsProviderSelect', function() {
			var voiceSource = $(this).val();
			// 清空并隐藏模型下拉框
			$('#ttsModels').empty().append('<option value="">' + i18n('ivr.form.ttsModels.empty') + '</option>');
			$('#ttsModelsDiv').hide();

			loadTtsLanguages(voiceSource, function() {
				var ttsLanguageCode = $('#ttsLanguageCode').val();
				if (ttsLanguageCode) {
					loadTtsModels(voiceSource, ttsLanguageCode, function() {
						var ttsModels = $('#ttsModels').val();
						loadVoicesByVoiceSourceAndLanguage(voiceSource, ttsLanguageCode, ttsModels);
					});
				} else {
					$('#voiceCode').empty().append('<option value="">' + i18n('ivr.form.voiceCode.empty') + '</option>');
				}
			});
		});

		// TTS语言变更事件
		$(document).on('change', '#ttsLanguageCode', function() {
			var voiceSource = $('#ttsProviderSelect').val();
			var ttsLanguageCode = $(this).val();
			loadTtsModels(voiceSource, ttsLanguageCode, function() {
				var ttsModels = $('#ttsModels').val();
				loadVoicesByVoiceSourceAndLanguage(voiceSource, ttsLanguageCode, ttsModels);
			});
		});

		// TTS模型变更事件
		$(document).on('change', '#ttsModels', function() {
			var voiceSource = $('#ttsProviderSelect').val();
			var ttsLanguageCode = $('#ttsLanguageCode').val();
			var ttsModels = $(this).val();
			loadVoicesByVoiceSourceAndLanguage(voiceSource, ttsLanguageCode, ttsModels);
		});

		// 绑定AI转接类型改变事件
		$(document).on('change', '#action', function() {
			toggleTransferFields();
		});

		// 初始化转接字段显示状态
		toggleTransferFields();

		// 初始化字段显示状态
		toggleFieldsByParentNode();

		var ttsTextWav = /*[[${ccIvr.ttsTextWav}]]*/ '';
		if (ttsTextWav && ttsTextWav.endsWith(".wav")) {
			var ttsTextfileUrl = /*[[${ccIvr.ttsTextfileUrl}]]*/ '';
			showTtsTextAudioPreview(ttsTextfileUrl);
		}

		var pressKeyInvalidTipsWav = /*[[${ccIvr.pressKeyInvalidTipsWav}]]*/ '';
		if (pressKeyInvalidTipsWav && pressKeyInvalidTipsWav.endsWith(".wav")) {
			var invalidTipsfileUrl = /*[[${ccIvr.invalidTipsfileUrl}]]*/ '';
			showInvalidTipsAudioPreview(invalidTipsfileUrl);
		}

		// hangupTips回显和预览
		var hangupTipsWav = /*[[${ccIvr.hangupTipsWav}]]*/ '';
		if (hangupTipsWav && hangupTipsWav.endsWith(".wav")) {
			var hangupTipsfileUrl = /*[[${ccIvr.hangupTipsfileUrl}]]*/ '';
			showHangupTipsAudioPreview(hangupTipsfileUrl);
		}

		// 确保digitRange有值
		var $digitRange = $('#digitRange');
		if (!$digitRange.val().trim()) {
			$digitRange.val('^[0-9]$');
		}

		// 设置pressKeyInvalidTips默认值（从i18n读取）
		var pressKeyInvalidTipsVal = /*[[${ccIvr.pressKeyInvalidTips}]]*/ '';
		if (!pressKeyInvalidTipsVal) {
			var defaultInvalidTips = /*[[#{ivr.form.pressKeyInvalidTips.default}]]*/ '输入错误，请重新输入';
			$('#pressKeyInvalidTips').val(defaultInvalidTips);
		}

		// ========== 变量选择功能初始化 ==========
		loadVariablesFromApi().then(function() {
			initVariableSelector();
		});

		// 绑定TTS合成按钮事件
		$(document).on('click', '.btn-tts-synthesize', function() {
			var fieldId = $(this).data('field');
			performTtsSynthesis(fieldId);
		});
	});

	function submitHandler() {
		// 设置默认值逻辑
		var action = $('#action').val();

		// 1. 当action为play时，minLen和maxLen设为1
		if (action === 'play') {
			$('#minLen').val('1');
			$('#maxLen').val('1');
		}

		if ($.validate.form()) {
			$.operate.save(prefix + "/add", $('#form-ivr-add').serialize());
		}
	}

	function toggleTransferFields() {
		var action = $('#action').val();
		console.log(action);
		$('.transfer-field').hide();
		// 根据转接类型显示对应字段
		if (action === 'acd') {
			$('.acd-transfer').show();
		} else if (action === 'gateway') {
			$('.gateway-transfer').show();
		} else if (action === 'extension') {
			$('.extension-transfer').show();
		} else if (action === 'playAndGetDigits') {
			$('.ivr-transfer').show();
		} else if (action === 'ai') {
			$('.ai-transfer').show();
		}

		// 处理play action的minLen和maxLen字段显示/隐藏
		if (action === 'play') {
			$('.length-field').hide();
		} else {
			$('.length-field').show();
		}
	}

	function toggleFieldsByParentNode() {
		var parentNodeId = $('#parentNodeId').val();
		if (parentNodeId === '0') {
			// 根节点：隐藏按键，显示TTS提供商、语言和音色
			$('select[name="digit"]').closest('.form-group').hide();
			$('.col-xs-12').has('select[name="ttsProvider"]').show();
			$('#ttsLanguageCodeDiv').show();
			$('#ttsModelsDiv').show();
			$('.col-xs-12').has('select[name="voiceCode"]').show();
			// 根据语言选项数量决定是否显示语言选择
			var ttsLanguageCount = $('#ttsLanguageCode option').length;
			if (ttsLanguageCount <= 1) {
				$('#ttsLanguageCodeDiv').hide();
			}
			// 根据模型选项数量决定是否显示模型选择
			var ttsModelsCount = $('#ttsModels option').length;
			if (ttsModelsCount <= 1) {
				$('#ttsModelsDiv').hide();
			}
		} else {
			// 子节点：显示按键，隐藏TTS提供商、语言和音色
			$('select[name="digit"]').closest('.form-group').show();
			$('.col-xs-12').has('select[name="ttsProvider"]').hide();
			$('#ttsLanguageCodeDiv').hide();
			$('#ttsModelsDiv').hide();
			$('.col-xs-12').has('select[name="voiceCode"]').hide();
		}
	}

	// 打开文件上传模态框
	function openUploadModal(fieldId, uploadType) {
		var modalHtml = `
        <div class="modal fade" id="uploadModal" tabindex="-1" role="dialog" aria-labelledby="uploadModalLabel">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                        <h4 class="modal-title" id="uploadModalLabel">` + i18n("ivr.modal.upload.title") + `</h4>
                    </div>
                    <div class="modal-body">
                        <form id="uploadForm" enctype="multipart/form-data">
                            <div class="form-group">
                                <label>` + i18n("ivr.modal.upload.label") + `</label>
                                <input type="file" id="fileInput" name="file" accept=".wav"
                                       class="form-control" style="height:auto;">
                                <span class="help-block">` + i18n("ivr.modal.upload.helpblock") + `</span>
                            </div>
                            <div class="form-group" id="uploadProgress" style="display:none;">
                                <label>` + i18n("ivr.modal.upload.progress") + `</label>
                                <div class="progress">
                                    <div class="progress-bar" role="progressbar" style="width: 0%;">
                                        0%
                                    </div>
                                </div>
                            </div>
                        </form>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-default" data-dismiss="modal">` + i18n("btn.cancel") + `</button>
                        <button type="button" class="btn btn-primary" id="confirmUpload">` + i18n("ivr.modal.upload.confirm") + `</button>
                    </div>
                </div>
            </div>
        </div>
    `;

		$('#uploadModal').remove();
		$('body').append(modalHtml);

		var $modal = $('#uploadModal');
		var $fileInput = $('#fileInput');

		$modal.modal('show');

		$('#confirmUpload').off('click').on('click', function() {
			var file = $fileInput[0].files[0];
			if (!file) {
				top.layer.msg(i18n("ivr.msg.selectFile"), {icon: 2});
				return;
			}

			if (!validateAudioFile(file)) {
				return;
			}

			var rootId = $('#rootId').val();
			uploadFileWithProgress(file, fieldId, rootId, function(success, result) {
				$modal.modal('hide');
				if (success) {
					if (fieldId === 'ttsText') {
						$('#ttsTextWav').val(result.filePath);
						showTtsTextAudioPreview(result.fileUrl);
					} else if (fieldId === 'pressKeyInvalidTips') {
						$('#pressKeyInvalidTipsWav').val(result.filePath);
						showInvalidTipsAudioPreview(result.fileUrl);
					} else if (fieldId === 'hangupTips') {
						$('#hangupTipsWav').val(result.filePath);
						showHangupTipsAudioPreview(result.fileUrl);
					}
					top.layer.msg(i18n("ivr.msg.uploadSuccess"), {icon: 1});
				} else {
					top.layer.msg(i18n("ivr.msg.uploadFail") + result, {icon: 2});
				}
			});
		});

		$modal.off('hidden.bs.modal').on('hidden.bs.modal', function() {
			$modal.remove();
		});
	}

	// 验证音频文件
	function validateAudioFile(file) {
		if (!file.name.toLowerCase().endsWith('.wav')) {
			top.layer.msg(i18n("ivr.msg.wavOnly"), {icon: 2});
			return false;
		}

		var maxSize = 50 * 1024 * 1024;
		if (file.size > maxSize) {
			top.layer.msg(i18n("ivr.msg.fileSizeLimit"), {icon: 2});
			return false;
		}

		return true;
	}

	// 带进度条上传
	function uploadFileWithProgress(file, fieldId, rootId, callback) {
		var formData = new FormData();
		formData.append('file', file);
		formData.append('rootId', rootId);

		$('#uploadProgress').show();

		$.ajax({
			url: ctx + 'cc/ivr/uploadVoice',
			type: 'POST',
			data: formData,
			processData: false,
			contentType: false,
			xhr: function() {
				var xhr = $.ajaxSettings.xhr();
				if (xhr.upload) {
					xhr.upload.addEventListener('progress', function(e) {
						if (e.lengthComputable) {
							var percent = Math.floor((e.loaded / e.total) * 100);
							$('.progress-bar').css('width', percent + '%').text(percent + '%');
						}
					}, false);
				}
				return xhr;
			},
			success: function(rsp) {
				if (rsp.code === 0) {
					callback(true, rsp.data);
				} else {
					callback(false, rsp.msg);
				}
			},
			error: function(xhr, status, error) {
				callback(false, i18n("ivr.msg.networkError") + error);
			}
		});
	}

	// 显示音频预览
	function showTtsTextAudioPreview(fileUrl) {
		if (fileUrl && $('#ttsAudioPreview').length) {
			$('#ttsAudioPreview audio source').attr('src', ctx + fileUrl);
			$('#ttsAudioPreview audio')[0].load();
			$('#ttsAudioPreview').show();
		}
	}

	function showInvalidTipsAudioPreview(fileUrl) {
		if (fileUrl && $('#invalidTipsAudioPreview').length) {
			$('#invalidTipsAudioPreview audio source').attr('src', ctx + fileUrl);
			$('#invalidTipsAudioPreview audio')[0].load();
			$('#invalidTipsAudioPreview').show();
		}
	}

	function showHangupTipsAudioPreview(fileUrl) {
		if (fileUrl && $('#hangupTipsAudioPreview').length) {
			$('#hangupTipsAudioPreview audio source').attr('src', ctx + fileUrl);
			$('#hangupTipsAudioPreview audio')[0].load();
			$('#hangupTipsAudioPreview').show();
		}
	}

	// ========== 工具函数 ==========

	// 根据TTS厂商加载语言列表
	function loadTtsLanguages(voiceSource, callback) {
		var languageSelect = $('#ttsLanguageCode');
		var languageDiv = $('#ttsLanguageCodeDiv');
		var modelsSelect = $('#ttsModels');
		var modelsDiv = $('#ttsModelsDiv');

		if (!voiceSource) {
			languageSelect.empty().append('<option value="">' + i18n('ivr.form.ttsLanguageCode.empty') + '</option>');
			languageDiv.hide();
			// 清空并隐藏模型下拉框
			modelsSelect.empty().append('<option value="">' + i18n('ivr.form.ttsModels.empty') + '</option>');
			modelsDiv.hide();
			if (callback) callback();
			return;
		}

		$.ajax({
			url: ctx + "aicall/ttsAliyun/tts/language",
			data: { voiceSource: voiceSource },
			success: function(rsp) {
				languageSelect.empty();

				if (rsp.data && rsp.data.length > 0) {
					// 如果只有一个选项，直接选中且不显示下拉框，但仍需调用models接口
					if (rsp.data.length === 1) {
						var item = rsp.data[0];
						var langCode = item.code || item.key || item.value;
						languageSelect.append($("<option>").attr("value", langCode).text(item.name || item.label || item.text || item.value));
						languageSelect.val(langCode);
						languageDiv.hide();
						// 单条数据默认选中时也要加载models
						loadTtsModels(voiceSource, langCode, function() {
							// 获取保存的模型值或当前选中的模型值
							var savedTtsModels = /*[[${ccIvr.ttsModels}]]*/ '';
							var modelValue = savedTtsModels || $('#ttsModels').val();
							loadVoicesByVoiceSourceAndLanguage(voiceSource, langCode, modelValue);
							if (callback) callback();
						});
					} else {
						languageSelect.append('<option value="">' + i18n('ivr.form.ttsLanguageCode.empty') + '</option>');
						rsp.data.forEach(function(item) {
							languageSelect.append($("<option>").attr("value", item.code || item.key || item.value).text(item.name || item.label || item.text || item.value));
						});
						languageDiv.show();
						// 多语言时，先清空并隐藏模型下拉框，等待语言选择后再加载
						modelsSelect.empty().append('<option value="">' + i18n('ivr.form.ttsModels.empty') + '</option>');
						modelsDiv.hide();
						if (callback) callback();
					}
				} else {
					languageSelect.append('<option value="">' + i18n('ivr.form.ttsLanguageCode.empty') + '</option>');
					languageDiv.show();
					// 无数据时隐藏模型下拉框
					modelsSelect.empty().append('<option value="">' + i18n('ivr.form.ttsModels.empty') + '</option>');
					modelsDiv.hide();
					if (callback) callback();
				}
			}
		});
	}

	// 根据TTS厂商和语言加载TTS模型列表
	function loadTtsModels(voiceSource, ttsLanguageCode, callback) {
		var modelsSelect = $('#ttsModels');
		var modelsDiv = $('#ttsModelsDiv');

		if (!voiceSource || !ttsLanguageCode) {
			modelsSelect.empty().append('<option value="">' + i18n('ivr.form.ttsModels.empty') + '</option>');
			modelsDiv.hide();
			if (callback) callback();
			return;
		}

		$.ajax({
			url: ctx + "aicall/ttsAliyun/tts/models",
			data: {
				voiceSource: voiceSource,
				ttsLanguageCode: ttsLanguageCode
			},
			success: function(rsp) {
				modelsSelect.empty();

				if (rsp.data && rsp.data.length > 0) {
					// 如果只有一个选项，直接选中且不显示下拉框
					if (rsp.data.length === 1) {
						var item = rsp.data[0];
						var modelValue = item.code || item.key || item.value || item;
						modelsSelect.append($("<option>").attr("value", modelValue).text(item.name || item.label || item.text || item.value || item));
						modelsSelect.val(modelValue);
						modelsDiv.hide(); // 单值时隐藏
					} else {
						modelsSelect.append('<option value="">' + i18n('ivr.form.ttsModels.empty') + '</option>');
						rsp.data.forEach(function(item) {
							modelsSelect.append($("<option>").attr("value", item.code || item.key || item.value || item).text(item.name || item.label || item.text || item.value || item));
						});
						modelsDiv.show(); // 多值时显示
					}
				} else {
					modelsSelect.append('<option value="">' + i18n('ivr.form.ttsModels.empty') + '</option>');
					modelsDiv.hide(); // 无数据时隐藏
				}

				if (callback) callback();
			}
		});
	}

	// 根据TTS厂商、语言和模型加载音色
	function loadVoicesByVoiceSourceAndLanguage(voiceSource, ttsLanguageCode, ttsModels) {
		var voiceSelect = $('#voiceCode');
		if (!voiceSource || !ttsLanguageCode) {
			voiceSelect.empty().append('<option value="">' + i18n('ivr.form.voiceCode.empty') + '</option>');
			return;
		}
		$.ajax({
			url: ctx + "aicall/ttsAliyun/getByLanguageCode",
			data: {
				voiceSource: voiceSource,
				ttsLanguageCode: ttsLanguageCode,
				ttsModels: ttsModels || ''
			},
			success: function(rsp) {
				voiceSelect.empty();
				voiceSelect.append('<option value="">' + i18n('ivr.form.voiceCode.empty') + '</option>');
				rsp.data.forEach(function(voice) {
					voiceSelect.append($("<option>")
							.attr("value", voice.voiceCode)
							.attr("data-source", voice.voiceSource)
							.text(voice.voiceName));
				});
				// 回显已保存的音色 - 确保在选项加载完成后设置
				var voiceCode = /*[[${ccIvr.voiceCode}]]*/ '';
				if (voiceCode) {
					voiceSelect.val(voiceCode);
				}
			}
		});
	}

	// ========== 变量选择功能 ==========
	function initVariableSelector() {
		// 为指定的textarea添加输入事件监听
		$('#ttsText, #pressKeyInvalidTips, #hangupTips').on('input', function(e) {
			checkForDoubleSlash($(this), e);
		});

		// 点击其他地方关闭变量选择器
		$(document).on('click', function(e) {
			if (!$(e.target).closest('#variableSelector').length &&
					!$(e.target).is('#ttsText, #pressKeyInvalidTips')) {
				hideVariableSelector();
			}
		});

		// 页面滚动时重新定位
		$(window).on('scroll', function() {
			if ($('#variableSelector').is(':visible')) {
				positionVariableSelector();
			}
		});

		// 初始化选择器内容
		initVariableContent();
	}


	// 检查是否输入了双斜杠
	function checkForDoubleSlash($textarea, e) {
		var cursorPos = $textarea[0].selectionStart;
		var text = $textarea.val();

		// 检查光标前两个字符是否是//
		if (cursorPos >= 2) {
			var lastTwoChars = text.substring(cursorPos - 2, cursorPos);
			if (lastTwoChars === '//') {
				// 保存当前textarea和光标位置
				window.currentTextarea = $textarea;
				window.slashPosition = cursorPos - 2;

				// 显示变量选择器
				showVariableSelector();
			}
		}
	}

	// 显示变量选择器
	function showVariableSelector() {
		var $modal = $('#variableSelectorModal');
		var $textarea = window.currentTextarea;

		if (!$textarea) return;

		// 定位模态框在textarea附近
		var textareaOffset = $textarea.offset();
		var modalWidth = 400; // 与modal-dialog样式一致

		var top = textareaOffset.top + $textarea.outerHeight() + 5;
		var left = textareaOffset.left + ($textarea.outerWidth() - modalWidth) / 2;

		// 确保不超出视口
		if (left < 10) left = 10;
		if (left + modalWidth > $(window).width() - 10) {
			left = $(window).width() - modalWidth - 10;
		}

		// 设置模态框位置
		$modal.css({
			'position': 'absolute',
			'top': top,
			'left': left
		});

		// 显示模态框
		$modal.modal('show');

		// 滚动到顶部
		$('#variableList').parent().scrollTop(0);
	}

	// 插入变量到textarea
	function insertVariable($textarea, slashPosition, variableValue) {
		var text = $textarea.val();
		var beforeSlash = text.substring(0, slashPosition);
		var afterSlash = text.substring(slashPosition + 2); // +2 to skip the //

		// 构建新文本：用{variable}替换//
		var newText = beforeSlash + '{' + variableValue + '}' + afterSlash;
		$textarea.val(newText);

		// 设置光标位置到变量后
		var newCursorPos = slashPosition + variableValue.length + 2; // +2 for { and }
		$textarea[0].setSelectionRange(newCursorPos, newCursorPos);

		// 触发输入事件
		$textarea.trigger('input');

		// 确保焦点回到文本框，可以继续输入
		$textarea.focus();
	}

	function loadVariablesFromApi() {
		return $.ajax({
			url: ctx + "system/params/getByParamCode",
			type: "GET",
			data: {
				paramCode: 'tts_content_variables',
				defaultValue: '{}'
			},
			dataType: "json",
			success: function(rsp) {
				availableVariables = []; // 清空数组
				var dataObj = null;

				// 判断返回值是字符串还是对象，并进行解析
				if (typeof rsp.data === 'string') {
					try {
						dataObj = JSON.parse(rsp.data);
					} catch (e) {
						console.error('解析变量JSON失败:', e);
						dataObj = {};
					}
				} else if (typeof rsp.data === 'object' && rsp.data !== null) {
					dataObj = rsp.data;
				}

				// 将 {key: value} 转换为数组格式
				if (dataObj) {
					Object.entries(dataObj).forEach(function([key, value]) {
						availableVariables.push({
							value: key,
							name: value
						});
					});
				}

				// 如果API返回空数据，设置默认值
				if (availableVariables.length === 0) {
					availableVariables = [];
				}
			},
			error: function() {
				// 网络错误时使用默认值
				availableVariables = [];
			}
		});
	}

	// 3. 新增函数：初始化变量列表内容
	function initVariableContent() {
		var $variableList = $('#variableList');

		// 清空并重新填充变量列表
		$variableList.empty();
		availableVariables.forEach(function(variable) {
			$variableList.append(
					$('<tr class="variable-item" style="cursor: pointer;"></tr>')
							.attr('data-value', variable.value)
							.html('<td style="padding: 6px 12px;"><code>{' + variable.value + '}</code></td><td style="padding: 6px 12px;">' + variable.name + '</td>')
			);
		});

		// 绑定变量选择事件
		$variableList.off('click').on('click', '.variable-item', function(e) {
			e.preventDefault();
			var variableValue = $(this).data('value');
			insertVariable(window.currentTextarea, window.slashPosition, variableValue);
			hideVariableSelector();
		});

		// 添加行悬停效果
		$variableList.off('mouseenter mouseleave').on('mouseenter', '.variable-item', function() {
			$(this).css('background-color', '#f0f8ff');
		}).on('mouseleave', '.variable-item', function() {
			$(this).css('background-color', '');
		});
	}

	// 4. 新增函数：显示变量选择器
	function showVariableSelector() {
		$('#variableSelector').show();
		initVariableContent();
		positionVariableSelector();
	}

	// 5. 新增函数：隐藏变量选择器
	function hideVariableSelector() {
		$('#variableSelector').hide();
		window.currentTextarea = null;
		window.slashPosition = null;
	}

	// 6. 新增函数：定位变量选择器到输入框旁边
	function positionVariableSelector() {
		var $selector = $('#variableSelector');
		var $textarea = window.currentTextarea;

		if (!$textarea || !$selector.is(':visible')) return;

		var textareaOffset = $textarea.offset();
		var textareaHeight = $textarea.outerHeight();

		// 计算位置：在textarea正下方
		var top = textareaOffset.top + textareaHeight;
		var left = textareaOffset.left;

		// 确保不超出视口
		var selectorWidth = $selector.outerWidth();
		if (left + selectorWidth > $(window).width() - 10) {
			left = $(window).width() - selectorWidth - 10;
		}

		// 设置位置
		$selector.css({
			'top': top,
			'left': left
		});
	}

	// ========== TTS合成功能 ==========
	function performTtsSynthesis(fieldId) {
		// 获取参数
		var rootId = $('#rootId').val();
		var voiceSource = $('#ttsProviderSelect').val();
		var voiceCode = $('select[name="voiceCode"]').val();
		var ttsText = $('#' + fieldId).val();

		if (!ttsText) {
			top.layer.msg(i18n("ivr.msg.ttsTextRequired"), {icon: 2});
			return;
		}

		// 显示加载提示
		var loadingIndex = top.layer.msg(i18n("ivr.msg.ttsSynthesizing"), {
			icon: 16,
			shade: 0.3,
			time: 0 // 不自动关闭
		});

		// 发送TTS合成请求
		$.ajax({
			url: ctx + 'cc/ivr/tts',
			type: 'GET',
			data: {
				rootId: rootId,
				voiceSource: voiceSource,
				voiceCode: voiceCode,
				ttsText: ttsText
			},
			dataType: "json",
			success: function(rsp) {
				top.layer.close(loadingIndex);

				if (rsp.code === 0) {
					// 成功处理
					if (rsp.data) {
						var filePath = rsp.data.filePath || '';
						var fileUrl = rsp.data.fileUrl || '';

						// 根据字段类型更新对应的Wav字段和预览
						if (fieldId === 'ttsText') {
							$('#ttsTextWav').val(filePath);
							showTtsTextAudioPreview(fileUrl);
						} else if (fieldId === 'pressKeyInvalidTips') {
							$('#pressKeyInvalidTipsWav').val(filePath);
							showInvalidTipsAudioPreview(fileUrl);
						} else if (fieldId === 'hangupTips') {
							$('#hangupTipsWav').val(filePath);
							showHangupTipsAudioPreview(fileUrl);
						}
						top.layer.msg(i18n("ivr.msg.ttsSuccess"), {icon: 1});
					} else {
						top.layer.msg(i18n("ivr.msg.ttsDataError"), {icon: 2});
					}
				} else {
					// 失败处理
					var errorMsg = rsp.msg || i18n("ivr.msg.ttsFail");
					top.layer.msg(errorMsg, {icon: 2});
				}
			},
			error: function(xhr, status, error) {
				top.layer.close(loadingIndex);
				top.layer.msg(error, {icon: 2});
			}
		});
	}

</script>
</body>
</html>