<template>
  <div>
    <div class="algorithm-detail" v-loading="loading">
      <div class="algo-name">
        <div>【{{ curRow?.name }}】</div>
        <div class="algo-set" @click="isParamSetVisible = true" v-if="hasSetParamPermission()">
          <el-icon><Setting /></el-icon>
          设置默认参数
        </div>
      </div>
      <div class="algo-title">
        <div class="title">算法介绍</div>
        <el-icon class="edit-icon" :size="16" @click="changeEditStatus" v-if="hasAlgoEditPermission()"
          ><EditPen
        /></el-icon>
      </div>
      <div class="media-section">
        <template v-if="editParam.url">
          <el-image
            v-if="isImage(editParam.url)"
            class="media-img"
            :src="editParam.url"
            :preview-src-list="[editParam.url]"
            :preview-teleported="true"
            fit="cover"
          />
          <video class="media-video" v-else :src="editParam.url" controls />
          <div class="media-set" v-if="isEditing">
            <el-upload
              :action="actionUrl"
              :show-file-list="false"
              :on-success="handleUpload"
              :headers="getHeaders()"
              :data="{ bizType: 'ALGO' }"
            >
              <el-icon class="icon-upload" :size="20"><Upload /></el-icon>
            </el-upload>
            <el-icon class="icon-delete" :size="20" @click="handleDelete"><Delete /></el-icon>
          </div>
        </template>
        <template v-else>
          <div class="empty-media">
            <img src="@/assets/images/algo/no-algo-url.png" alt="" width="200" height="200" />
            <el-upload
              v-if="isEditing"
              :action="actionUrl"
              :show-file-list="false"
              :on-success="handleUpload"
              :headers="getHeaders()"
              :data="{ bizType: 'ALGO' }"
            >
              <div class="empty-media-text">请点击上传算法介绍图片或视频</div>
            </el-upload>
          </div>
        </template>
      </div>
      <el-card class="remark-card">
        <template v-if="!isEditing">
          <div v-for="(line, idx) in remarkLines" :key="idx">{{ line }}</div>
        </template>
        <template v-else>
          <el-input
            v-model="editParam.remark"
            type="textarea"
            :autosize="{ minRows: 4, maxRows: 8 }"
            placeholder="请输入算法描述"
          />
        </template>
      </el-card>
      <div class="btn-group" v-if="isEditing">
        <el-button @click="cancelEdit">取消</el-button>
        <el-button type="primary" @click="saveChanges">保存</el-button>
      </div>
    </div>
    <el-dialog
      v-model="isParamSetVisible"
      title="请输入代码修改算法参数，提交后生效"
      width="60%"
      align-center
      @close="cancelAlgoParamsEdit"
    >
      <json-editor-vue
        class="json-editor"
        v-model="extraJson"
        :language="'zh-CN'"
        @update:modelValue="handleUpdateAlgoParam"
        @validationError="editError"
      />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cancelAlgoParamsEdit">取消</el-button>
          <el-button type="primary" @click="saveAlgoParamsChanges"> 提交 </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
  import urlJoin from 'url-join';
  import { storeToRefs } from 'pinia';
  import { ref, computed, watch, nextTick } from 'vue';
  import { ElButton, ElIcon, ElMessage, ElUpload, ElDialog, ElInput, ElCard } from 'element-plus';
  import { EditPen, Upload, Delete, Setting } from '@element-plus/icons-vue';
  import { useGlobSetting } from '@/hooks/setting';
  import { useUserStore } from '@/store/modules/user';
  import { getHeaders } from '@/utils/http/axios';
  import { useAlgoDataStore } from '../useAlgoData';
  import { PERM_ALGO } from '@/types/permission/constants';
  import { UpdateAlgoParamParams, updateAlgoParam } from '@/api/algo/algo';
  import JsonEditorVue from 'json-editor-vue3';

  const { urlPrefix } = useGlobSetting();
  const userStore = useUserStore();

  const algoDataStore = useAlgoDataStore();
  const { curRow } = storeToRefs(algoDataStore);
  const { updateCurRow } = algoDataStore;

  const loading = ref(false);
  const isParamSetVisible = ref(false);
  const isEditing = ref(false);
  const editParam = ref<UpdateAlgoParamParams>({});
  const extraJson = ref({});

  const remarkLines = computed(() => (curRow.value?.remark ? curRow.value?.remark.split(/\r?\n/) : []));

  const actionUrl = computed(() => {
    return urlJoin(urlPrefix!, `/admin/minio/uploadFile`);
  });

  function initEditParam() {
    editParam.value.algoId = curRow.value?.id;
    editParam.value.algoParam = curRow.value?.extra;
    editParam.value.remark = curRow.value?.remark;
    editParam.value.url = curRow.value?.url;
    extraJson.value = JSON.parse(curRow.value?.extra || '{}');
  }

  function isImage(url: string) {
    return /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(url);
  }

  watch(
    curRow,
    () => {
      if (curRow.value) {
        initEditParam();
        loading.value = false;
      }
    },
    { immediate: true, deep: true },
  );

  // 默认参数设置权限
  const hasSetParamPermission = () => {
    return userStore.checkPermission(PERM_ALGO.PREVIEW_PARAM_DEFAULT);
  };
  // 算法介绍设置权限
  const hasAlgoEditPermission = () => {
    return userStore.checkPermission(PERM_ALGO.PREVIEW_DESCRIPTION);
  };

  const handleUpload = (res) => {
    editParam.value.url = res.data.url;
  };

  const handleDelete = () => {
    editParam.value.url = '';
  };

  const changeEditStatus = () => {
    isEditing.value = !isEditing.value;
    initEditParam();
  };

  const saveChanges = () => {
    if (!editParam.value.remark) {
      ElMessage({
        message: '算法描述不可为空',
        type: 'warning',
      });
      return;
    }
    loading.value = true;
    updateAlgoParam(editParam.value).then(() => {
      updateCurRow(curRow.value!);
      ElMessage({
        message: '保存成功',
        type: 'success',
      });
      nextTick(() => {
        isEditing.value = false;
        loading.value = false;
      });
    });
  };

  const cancelEdit = () => {
    isEditing.value = false;
    initEditParam();
  };

  const handleUpdateAlgoParam = (newJsonData) => {
    editParam.value.algoParam = newJsonData;
  };

  const cancelAlgoParamsEdit = () => {
    isParamSetVisible.value = false;
    initEditParam();
  };

  const saveAlgoParamsChanges = () => {
    updateAlgoParam(editParam.value).then(() => {
      updateCurRow(curRow.value!);
      ElMessage({
        message: '算法参数设置成功',
        type: 'success',
      });
      isParamSetVisible.value = false;
    });
  };

  const editError = (_editor: any, errors: any[]) => {
    if (errors.length > 0) {
      ElMessage({
        message: 'JSON 格式错误，请检查',
        type: 'error',
      });
    }
  };
</script>

<style scoped lang="scss">
  .algorithm-detail {
    height: 100%;
    padding: 20px 8px;

    .algo-name {
      font-size: 20px;
      font-weight: bold;
      margin-bottom: 16px;
      display: flex;
      align-items: center;

      .algo-set {
        font-size: 14px;
        color: #409eff;
        cursor: pointer;
        display: flex;
        align-items: center;
        margin-left: 10px;

        .el-icon {
          margin-right: 5px;
        }
      }
    }

    .algo-title {
      height: 22px;
      display: flex;
      align-items: center;
      margin: 16px 0 8px 12px;
      font-weight: 600;

      .title {
        line-height: 22px;
        margin-left: 10px;
        position: relative;
      }

      .title::before {
        content: '';
        display: inline-block;
        width: 3px;
        height: 14px;
        background-color: #409eff;
        border-radius: 1px;
        position: absolute;
        left: -10px;
        top: 50%;
        transform: translateY(-50%);
      }

      .edit-icon {
        margin-left: 8px;
        color: #409eff;
        cursor: pointer;
      }
    }
  }

  .media-section {
    height: 40%;
    margin: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    position: relative;

    .media-img,
    .media-video {
      height: 100%;
    }

    .media-img .img {
      cursor: zoom-in;
    }

    .media-set {
      padding: 10px 5px;
      border-radius: 50px;
      position: absolute;
      top: 30%;
      right: 0;
      background: #fefefe;
      box-shadow: #cdcdcda3 2px 2px 4px 2px;
    }

    .icon-upload,
    .icon-delete {
      margin: 5px 0;
      cursor: pointer;
    }

    .icon-upload:hover,
    .icon-delete:hover {
      color: #409eff;
    }

    .icon-upload {
      margin-bottom: 20px;
    }
  }

  .empty-media {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    .empty-media-text {
      color: #409eff;
      cursor: pointer;
    }
  }

  .remark-card {
    height: 40%;
    margin: 0 10px 20px 10px;
    margin-bottom: 24px;
  }

  .btn-group {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
  }

  :deep(.el-dialog__body) {
    height: 500px;
    overflow: auto;
  }

  .json-editor {
    width: 100%;
    height: 100%;
  }
</style>
