<script setup lang="ts">
import type { CourseType, ExperimentInfo, ExperimentRecord } from '../types'
import { HomeFilled } from '@element-plus/icons-vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import DragPanel from '@/components/DragPanel.vue'
import { useGetCourseList } from '../composables/useGetCourseList'
import { upload } from '@/utils/upload'
import { getExperiment, getExperimentRecord, uploadExperimentPicture, submitExperimentRecord } from '../api'
import dayjs from 'dayjs'
import { saveAs } from 'file-saver'
import html2pdf from 'html2pdf.js'
import { useCookies } from '@vueuse/integrations/useCookies'
import { useAppConfig } from '@/composables/useAppConfig'
// import { useLiveMonitor } from '@/composables/useLiveMonitor'

const appConfig = useAppConfig()
// useLiveMonitor({ autoStart: !!appConfig.liveMonitor })

const Question = defineAsyncComponent(() => import('../components/Question.vue'))
const Info = defineAsyncComponent(() => import('../components/Info.vue'))
const Case = defineAsyncComponent(() => import('../components/Case.vue'))
const Book = defineAsyncComponent(() => import('../components/Book.vue'))
const Video = defineAsyncComponent(() => import('../components/Video.vue'))
const Discuss = defineAsyncComponent(() => import('../components/Discuss.vue'))
const Result = defineAsyncComponent(() => import('../components/Result.vue'))
const ReportDialog = defineAsyncComponent(() => import('../components/ReportDialog.vue'))
const ReportFilePreview = defineAsyncComponent(() => import('../components/ReportFilePreview.vue'))
const PrepareDialog = defineAsyncComponent(() => import('../components/PrepareDialog.vue'))
const ResultDialog = defineAsyncComponent(() => import('../components/ResultDialog.vue'))
const ReportPreview = defineAsyncComponent(() => import('../components/ReportPreview.vue'))
const Exam = defineAsyncComponent(() => import('../components/Exam.vue'))
const Example = defineAsyncComponent(() => import('../components/Example.vue'))

const route = useRoute()

// 左侧
const form = reactive<{ course_id: string; experiment_id: string }>({
  course_id: (route.query.course_id as string) || '',
  experiment_id: (route.query.experiment_id as string) || '',
})
// 课程列表
const { courses } = useGetCourseList()
// 实验列表
const experimentList = $computed(() => {
  const course = courses.value.find((item: CourseType) => item.id === form.course_id)
  return course?.experiments || []
})

watchEffect(() => {
  if (!form.course_id && courses.value.length) {
    const [first] = courses.value
    form.course_id = first.id
  }
  if (!form.experiment_id && experimentList.length) {
    const [first] = experimentList
    form.experiment_id = first.id
  }
})
// 课程改变
function handleCourseChange(value: string) {
  ElMessageBox.confirm('切换实验，将会导致当前操作内容变化，请确认当前操作无误并确认切换实验。', '提示').then(() => {
    form.course_id = value
    form.experiment_id = ''
    tabActive.value = 'info'
    empty.value = []
  })
}
// 实验改变
function handleExperimentChange(value: string) {
  ElMessageBox.confirm('切换实验，将会导致当前操作内容变化，请确认当前操作无误并确认切换实验。', '提示').then(() => {
    form.experiment_id = value
    tabActive.value = 'info'
    empty.value = []
  })
}

let detail = $ref<ExperimentRecord>()
provide('detail', $$(detail))

let experimentInfo = $ref<ExperimentInfo>()
provide('info', $$(experimentInfo))

function fetchInfo() {
  if (!form.experiment_id) return
  getExperiment({ experiment_id: form.experiment_id }).then((res) => {
    experimentInfo = res.data.detail
  })
}
function fetchExperimentRecord() {
  if (!form.experiment_id) return
  getExperimentRecord({ experiment_id: form.experiment_id }).then((res) => {
    if (Array.isArray(res.data.data)) {
      detail = undefined
    } else {
      detail = { ...res.data.data, is_check_report: res.data.is_check_report }
    }
  })
}

watchEffect(() => {
  fetchInfo()
  fetchExperimentRecord()
})

const tabActive = ref('info')
const examURL = ref('')

// 右侧
const cookies = useCookies(['TGC'])
const LAB_URL = computed<string>(() => {
  if (tabActive.value === 'exam' && examURL.value && experimentInfo?.exam_status === 1) return examURL.value
  if (experimentInfo?.type === 4)
    return `${appConfig.dmlURL || import.meta.env.VITE_DML_URL}${functionPath.value}?experiment_id=${
      form.experiment_id
    }`
  if (experimentInfo?.type === 5) return `${import.meta.env.VITE_SAAS_BI_URL}?experiment_id=${form.experiment_id}`
  if (experimentInfo?.type === 6) return `${import.meta.env.VITE_SAAS_AI_URL}?experiment_id=${form.experiment_id}`
  return `${import.meta.env.VITE_LAB_URL}&token=${cookies.get('TGC')}`
})

let iframeKey = $ref(Date.now())
// 返回首页
function handleBackHome() {
  ElMessageBox.confirm('此操作将会强制返回到实验室首页，您当前的操作内容有可能丢失，确定返回首页吗？', '提示').then(
    () => {
      iframeKey = Date.now()
    }
  )
}

const reportDialogVisible = $ref(false)
// 是否已经提交
const submitted = $computed(() => {
  // status: 0 缓存 1 已提交 2 已评分
  // 已提交
  if (detail?.status === 1) return true
  // 已评分并且可以重复提交
  if (detail?.status === 2 && experimentInfo?.can_repeat_commit !== 1) return true
  return false
})
// 是否禁用
const disabled = $computed(() => {
  return submitted || !form.experiment_id
})
const iframeRef = $ref<HTMLIFrameElement>()

let screenshotLoading = $ref(false)
let screenshotTimestamp = $ref(0)
// 截图
function handleCapture() {
  const pictures = detail?.pictures || []
  if (pictures.length >= 20) {
    ElMessage.error('已达到单个实验最大截图数量，无法截图，请在过程与结果功能中删除多余截图之后再进行操作。')
    return
  }
  const iframeWindow = iframeRef?.contentWindow
  if (!iframeWindow) return
  screenshotTimestamp = Date.now()
  screenshotLoading = true
  // 发送截图消息
  iframeWindow?.postMessage({ action: 'screenshot', timestamp: screenshotTimestamp }, '*')
}
// 截图之后
function handleCaptureCallback(event: MessageEvent) {
  const { data } = event
  if (data.error) {
    screenshotLoading = false
    return
  }
  if (data.action === 'screenshot' && data.timestamp === screenshotTimestamp) {
    upload(data.blob).then((url) => {
      uploadPicture(url)
    })
  }
}
onMounted(() => {
  window.addEventListener('message', handleCaptureCallback, false)
})
onUnmounted(() => {
  window.removeEventListener('message', handleCaptureCallback, false)
})

// 上传截图
function uploadPicture(url: string) {
  const pictures = detail?.pictures || []
  pictures.unshift({ url, name: Date.now() + '.png', upload_time: dayjs().format('YYYY-MM-DD HH:mm:ss') })
  uploadExperimentPicture({ experiment_id: form.experiment_id, pictures: JSON.stringify(pictures) }).then(() => {
    fetchExperimentRecord()
    screenshotLoading = false
  })
}
// 提交实验
function handleSubmit() {
  ElMessageBox.confirm('此操作将会提交该实验，状态会变为已提交，您将不能再操作该实验，确定提交实验吗？', '提示').then(
    () => {
      submitExperimentRecord({ experiment_id: form.experiment_id }).then(() => {
        ElMessage({ message: '提交成功', type: 'success' })
        fetchExperimentRecord()
      })
    }
  )
}
let resizeKey = $ref(0)
function handleResize() {
  resizeKey = Date.now()
}

// 实验准备
const prepareDialogVisible = $ref(false)
// 实验结果
const resultDialogVisible = $ref(false)

// 查看实验报告
let reportFilePreviewVisible = $ref(false)
function handleReportView() {
  if (experimentInfo?.report_upload_way === 2) {
    window.open(`/student/lab/report/view/${experimentInfo?.id}`)
  } else {
    reportFilePreviewVisible = true
  }
}

// 导出实验报告
let isExport = $ref(false)
function handleReportExport() {
  if (!detail) return
  const filename = `${detail.student.sno_number}_${detail.student.name}_${detail.experiment.name}_实验报告`
  // 在线报告
  if (experimentInfo?.report_upload_way === 2) {
    console.log('在线报告导出')
    isExport = true
  } else {
    saveAs(detail.file.url, filename)
  }
}
function handleReportPreviewReady() {
  if (!detail) return
  const filename = `${detail.student.sno_number}_${detail.student.name}_${detail.experiment.name}_实验报告`
  const el: HTMLElement | null = document.querySelector('.report-preview__inner')
  if (!el) return
  setTimeout(() => {
    html2pdf()
      .set({ filename, html2canvas: { scale: 2, useCORS: true } })
      .from(el)
      .save()
    isExport = false
  }, 100)
}

const empty = ref<string[]>([])

function handleEmpty(name: string) {
  empty.value.push(name)
}
const functionPath = ref('')
function handleGoToFunction(path: string) {
  functionPath.value = path
}
</script>

<template>
  <DragPanel @resize="handleResize" :isLeftShow="appConfig.system === 'x' && experimentInfo?.exam_status === 1">
    <template #left>
      <div class="lab-left">
        <el-form :model="form" label-suffix=":" hide-required-asterisk>
          <el-form-item label="请选择课程">
            <el-select :model-value="form.course_id" @change="handleCourseChange" style="width: 100%">
              <el-option v-for="item in courses" :key="item.id" :label="item.name" :value="item.id"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="请选择实验" prop="experiment_id">
            <el-select :model-value="form.experiment_id" @change="handleExperimentChange" style="width: 100%">
              <el-option v-for="item in experimentList" :key="item.id" :label="item.name" :value="item.id"></el-option>
            </el-select>
          </el-form-item>
        </el-form>
        <el-tabs type="border-card" v-model="tabActive" v-if="experimentInfo">
          <el-tab-pane label="实验信息" name="info">
            <Info :data="experimentInfo"></Info>
          </el-tab-pane>
          <el-tab-pane label="实验案例" name="example" v-if="!empty.includes('example')">
            <Example
              :experiment_id="form.experiment_id"
              @empty="handleEmpty('example')"
              @goToFunction="handleGoToFunction"></Example>
          </el-tab-pane>
          <el-tab-pane label="案例原文" name="case" v-if="!empty.includes('case')">
            <Case
              :course_id="form.course_id"
              :experiment_id="form.experiment_id"
              :key="resizeKey"
              @empty="handleEmpty('case')"></Case>
          </el-tab-pane>
          <el-tab-pane label="实训指导" name="book" v-if="!empty.includes('book')">
            <Book
              :course_id="form.course_id"
              :experiment_id="form.experiment_id"
              :key="resizeKey"
              @empty="handleEmpty('book')"></Book>
          </el-tab-pane>
          <el-tab-pane label="操作视频" name="video" v-if="!empty.includes('video')">
            <Video
              :course_id="form.course_id"
              :experiment_id="form.experiment_id"
              @empty="handleEmpty('video')"></Video>
          </el-tab-pane>
          <el-tab-pane label="理论试题" name="exam" v-if="!empty.includes('exam')">
            <Exam
              v-model="examURL"
              :experiment_id="form.experiment_id"
              :examStatus="experimentInfo?.exam_status"
              :showIframe="experimentInfo?.exam_status === 0"
              @empty="handleEmpty('exam')"></Exam>
          </el-tab-pane>
          <el-tab-pane label="实操试题" name="qa" v-if="!empty.includes('qa')">
            <Question :experiment_id="form.experiment_id" @empty="handleEmpty('qa')"></Question>
          </el-tab-pane>
          <el-tab-pane label="过程与结果" name="result" lazy>
            <Result :data="experimentInfo" @update="fetchExperimentRecord"></Result>
          </el-tab-pane>
          <el-tab-pane label="讨论交流" name="discuss" lazy>
            <Discuss :experiment_id="form.experiment_id"></Discuss>
          </el-tab-pane>
        </el-tabs>
      </div>
    </template>
    <template #right>
      <AppCard>
        <div class="exam-status" v-if="appConfig.system === 'x' && experimentInfo?.exam_status === 1">
          <el-button type="primary" @click="tabActive = 'exam'">理论试题</el-button>
          <el-button type="primary" @click="tabActive = 'qa'">实操环境</el-button>
        </div>
        <el-row justify="space-between" v-else>
          <div>
            <el-button type="primary" :icon="HomeFilled" :disabled="submitted" @click="handleBackHome"
              >返回首页</el-button
            >
            <el-button type="primary" :disabled="disabled" @click="handleSubmit">提交实验</el-button>
          </div>
          <div>
            <!-- <el-button type="primary" v-if="appConfig.system == 'default'">
              <router-link to="/ai" target="_blank">AI数据分析</router-link>
            </el-button>-->
            <el-button type="primary" :disabled="disabled" :loading="screenshotLoading" @click="handleCapture"
              >截图</el-button
            >
            <el-button type="primary" :disabled="disabled" @click="prepareDialogVisible = true">实验准备</el-button>
            <el-button type="primary" :disabled="disabled" @click="resultDialogVisible = true">实验结果</el-button>
            <el-button
              type="primary"
              :disabled="disabled"
              v-if="experimentInfo?.report_upload_way === 2 && !experimentInfo?.is_commit_report">
              <router-link :to="`/student/lab/report/${form.experiment_id}`" target="_blank">在线实验报告</router-link>
            </el-button>
            <el-button
              type="primary"
              :disabled="disabled"
              @click="reportDialogVisible = true"
              v-if="experimentInfo?.report_upload_way === 1 && !submitted"
              >上传实验报告</el-button
            >
            <el-button type="primary" @click="handleReportView" v-if="experimentInfo?.is_commit_report"
              >查看实验报告</el-button
            >
            <el-button
              type="primary"
              @click="handleReportExport"
              v-if="detail?.status === 2 && experimentInfo?.is_commit_report"
              >导出实验报告</el-button
            >
          </div>
        </el-row>
      </AppCard>
      <div class="lab-box">
        <el-empty
          description="您已经提交该实验，不能再进行操作，切换其他实验再做操作吧。"
          style="flex: 1"
          v-if="submitted" />
        <template v-else>
          <template v-if="experimentInfo?.exam_status === 1 && tabActive === 'exam'">
            <Exam
              v-model="examURL"
              :showInfo="false"
              :showIframe="true"
              :experiment_id="form.experiment_id"
              :examStatus="experimentInfo?.exam_status"
              @empty="handleEmpty('exam')"></Exam>
          </template>
          <template v-else>
            <iframe
              allow="camera; microphone"
              allowfullscreen
              :src="LAB_URL"
              :key="iframeKey"
              frameborder="0"
              class="iframe"
              ref="iframeRef"></iframe>
            <div
              style="padding: 10px; background-color: #fff; width: 300px"
              v-if="experimentInfo?.exam_status === 1 && tabActive === 'qa'">
              <Question :experiment_id="form.experiment_id" :exam_status="experimentInfo?.exam_status"></Question>
            </div>
          </template>
        </template>
      </div>
    </template>
  </DragPanel>

  <!-- 上传报告 -->
  <ReportDialog
    v-model="reportDialogVisible"
    :data="experimentInfo"
    @update="fetchExperimentRecord"
    v-if="reportDialogVisible && experimentInfo"></ReportDialog>
  <ReportFilePreview
    v-model="reportFilePreviewVisible"
    :data="experimentInfo"
    v-if="reportFilePreviewVisible && experimentInfo"></ReportFilePreview>
  <!-- 实验准备 -->
  <PrepareDialog
    v-model="prepareDialogVisible"
    :data="experimentInfo"
    v-if="prepareDialogVisible && experimentInfo"></PrepareDialog>

  <!-- 实验结果 -->
  <ResultDialog
    v-model="resultDialogVisible"
    :data="experimentInfo"
    v-if="resultDialogVisible && experimentInfo"></ResultDialog>

  <!-- 导出在线报告 -->
  <template v-if="experimentInfo?.id && isExport">
    <ReportPreview :id="experimentInfo?.id" makePdf @ready="handleReportPreviewReady"></ReportPreview>
  </template>
</template>

<style lang="scss" scoped>
.lab-left {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: hidden;
  .el-tabs {
    flex: 1;
    border: 0;
    overflow: hidden;
  }
  :deep(.el-tabs__header) {
    background-color: #e1e4eb;
  }
  :deep(.el-tabs__item) {
    padding: 0 14px !important;
    border: 0;
    border-radius: 6px 6px 0px 0px;
  }
  :deep(.el-tabs__content) {
    height: calc(100% - 40px);
    box-sizing: border-box;
  }
  :deep(.el-tab-pane) {
    height: 100%;
    overflow-y: auto;
  }
}
.lab-box {
  position: relative;
  flex: 1;
  width: 100%;
  margin-top: 20px;
  display: flex;
}
.iframe {
  width: 100%;
  height: 100%;
}
</style>
