<script setup lang="ts">
import { useTitle }                         from '@/hooks/useTitle';
import { Dialog, Toast }                    from '@/platform';
import { saveFileMethod, uploadFileMethod } from '@/request/api/camera.api';
import { useVisitor }                       from '@/stores';
import { tryOnMounted, tryOnUnmounted }     from '@vueuse/core';
import { useForm, useRequest }              from 'alova/client';
import Segmented, { type ConfigProps }      from './camera.config';
import Camera                               from './camera.vue';


let audio: HTMLAudioElement | void;

const router = useRouter();
const title = useTitle();
const visitor = useVisitor();

const { form: dataset, loading: submitting, send: submit } = useForm(data => saveFileMethod(data), {
  initialForm: { patientId: visitor.patientId } as Record<string, any>,
}).onSuccess(({ data }) => {
  visitor.resultId = data.resultId;
  router.replace(data.route);
}).onError(() => {
  handle();
  step.value = 1;
});


const step = ref(0);
const snapshot = ref<string | void>();
const config = shallowRef<ConfigProps>();

const showExample = ref(false);

watch([ step, snapshot ], ([ step, snapshot ], old, onCleanup) => {
  const { before, after, ..._config } = Segmented[ step - 1 ];
  const old_audio = config.value?.audio;
  config.value = Object.assign(_config, snapshot ? after : before);

  if ( old_audio !== config.value.audio ) {
    audio?.pause();
    if ( config.value.audio && audio ) {
      audio.src = config.value.audio;
      audio.play()
           .catch(() => Dialog.show({ message: '开始拍摄', theme: 'round-button' }))
           .then(() => audio!.play());
    }
  }
  title.value = config.value.title;
});

const cameraRef = useTemplateRef<InstanceType<typeof Camera>>('camera');

const { loading: uploading, send: update, abort: stop } = useRequest((file: File) => uploadFileMethod(file), {
  immediate: false,
});

const handle = () => {
  if ( submitting.value ) return;
  if ( !showExample.value ) { snapshot.value = cameraRef.value?.handle(); }
  showExample.value = false;
  stop();
};
const next = async () => {
  if ( uploading.value || submitting.value ) return;
  if ( snapshot.value ) {
    uploading.value = true;
    const key = config.value!.key;

    const toast = Toast.loading(50, { message: '上传中...' });

    const response = await fetch(snapshot.value);
    const blob = await response.blob();
    const file = new File(
      [ blob ],
      `${ dataset.value.patientId }_${ key?.replace?.(/img/ig, '') }`,
      { type: blob.type },
    );
    try {
      const { url } = await update(file);
      dataset.value[ key ] = url;
    } finally {
      toast.close();
    }
  }

  if ( step.value === Segmented.length ) {
    submit();
  } else {
    handle();
    step.value += 1;
  }
};

tryOnMounted(() => {
  audio = document.createElement('audio');
  document.body.appendChild(audio);
});
tryOnUnmounted(() => {
  audio?.pause();
  audio = void 0;

  stop();
});
</script>
<template>
  <div class="flex flex-col">
    <header class="flex flex-col justify-center px-24">
      <div class="text-3xl text-center" :class="{ required: config?.required }">{{ config?.label }}</div>
      <div class="mt-8 text-lg text-center tracking-wider leading-10">{{ config?.description }}</div>
    </header>
    <main class="flex justify-center items-center">
      <Camera ref="camera" v-bind="config?.video" @loaded="step = 1;">
        <template #shade="{scale}">
          <component :is="config?.shade" :scale="scale"></component>
          <img v-if="showExample && config?.example" :src="config.example" alt="示例" @click="showExample = false" />
        </template>
      </Camera>
      <div v-if="config?.example"
           class="size-40 absolute -top-8 right-2 cursor-pointer hover:text-primary"
           @click="showExample = !showExample"
      >
        <img class="size-full object-scale-down" :src="config?.example" alt="示例" />
        <div class="mt-2 text-xl text-center">示例</div>
      </div>
    </main>
    <footer class="flex flex-col justify-center items-center">
      <div v-if="snapshot" class="flex justify-evenly w-full cursor-pointer">
        <div class="">
          <img class="h-20" src="@/assets/images/button-cancel.png" alt="重拍" @click="handle()" /></div>
        <div class="cursor-pointer">
          <img class="h-20" src="@/assets/images/button-confirm.png" alt="确认" @click="next()" />
        </div>
      </div>
      <div v-else-if="step" class="h-min text-center cursor-pointer hover:text-primary" @click="handle()">
        <button class="size-28 border-8 rounded-full hover:border-primary"></button>
        <div class="mt-8 text-3xl">{{ showExample ? '开始拍照' : '点击拍照' }}</div>
      </div>
    </footer>
  </div>
</template>
<style scoped lang="scss">
header, footer {
  flex: 1 1 20%;
}

main {
  position: relative;;
  flex: 1 1 40%;
}

.required {
  &::before {
    content: "*";
    margin-right: 4px;
    color: #f53030;
  }

}
</style>
