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


defineOptions({
  name: 'CameraPage',
});
const title = useTitle();

const step = ref(0);
const config = shallowRef<Omit<ConfigProps, 'before' | 'after'> & { type: 'before' | 'after'; label: string; }>();

const camera = useTemplateRef<InstanceType<typeof Camera>>('camera');
const area = reactive({
  // width: 295,
  // height: 400,
  width: 270,
  height: 366,
  multiple: 2,
});

onBeforeMount(() => next());

function next(half = false) {
  if ( half ) {
    const { after, before, ..._config } = Config[ step.value - 1 ];
    config.value = {
      ..._config, label: _config.title,
      ...after, type: 'after',
    };
  } else {
    const { after, before, ..._config } = Config[ step.value ];
    config.value = {
      ..._config, label: _config.title,
      ...before, type: 'before',
    };
    step.value += 1;
  }
  title.value = config.value.title;
}

function prev(half = false) {
  if ( half ) {
    const { after, before, ..._config } = Config[ step.value - 1 ];
    config.value = {
      ..._config, label: _config.title,
      ...before, type: 'before',
    };
  } else {
    const { after, before, ..._config } = Config[ step.value - 2 ];
    config.value = {
      ..._config, label: _config.title,
      ...before, type: 'before',
    };
    step.value -= 1;
  }
}

let done = () => {};

const visitor = useVisitor();
let play: (next: boolean) => void;
let timer: ReturnType<typeof setInterval>;

const router = useRouter();
const complete = ref(false);
const countdown = ref(0);

const { form: dataset, loading: submitting, send: submit } = useForm(data => saveFileMethod(data), {
  initialForm: { patientId: visitor.patientId } as Record<string, any>,
}).onSuccess(({ data }) => {
  done = () => { router.replace(data.path); };
  visitor.resultId = data.resultId;
  if ( data.done ) {
    complete.value = true;
    countdown.value = 5;
    timer = setInterval(() => { if ( countdown.value-- <= 0 ) done(); }, 1000);
  } else {
    done();
  }
});

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


const onStart = () => {
  if ( showExample.value ) return showExample.value = false;
  const resolvers = withResolvers<boolean>();
  play = resolvers.resolve;
  camera.value?.handle(resolvers.promise);
  next(true);
};


const onConfirm = async () => {
  if ( submitting.value ) return;

  const key = config.value!.key;
  const title = config.value!.title;
  // 创建文件
  const blob = await camera.value?.get('blob') as Blob;
  const file = new File([ blob ], `${ dataset.value.patientId }-${ title.slice(0, 2) }`, { type: blob.type });
  // 上传文件
  try {
    const { url } = await update(file);
    dataset.value[ key ] = url;
    if ( step.value == Config.length ) {
      submit();
    } else {
      next();
      play(true);
    }
  } catch ( error: any ) {
    console.log(`[log] 拍照上传错误`, error?.message ?? error);
    onCancel();
    play(true);
  }
};
const onCancel = () => {
  if ( submitting.value ) return;

  prev(true);
  play?.(true);

  stop();
};

tryOnUnmounted(() => {
  clearInterval(timer);
  stop();
});

const showExample = ref(false);
const transparency = ref(1);
</script>
<template>
  <div class="py-8 flex flex-col">
    <template v-if="complete">
      <header class="flex flex-col justify-center px-24" style="flex: 1 1 20%">
        <div class="text-3xl text-center">拍摄完成</div>
      </header>
      <main class="flex flex-col justify-evenly px-24" style="flex: 1 1 50%">
        <img class="size-40 mx-auto" src="@/assets/images/tips.png">
        <div>
          <div class="text-3xl text-center">恭喜您！</div>
          <div class="text-3xl text-center my-8">完成舌面象的采集</div>
        </div>
      </main>
      <footer class="flex justify-evenly items-start" style="flex: 1 1 30%">
        <van-button class="decorate !text-xl !text-primary-400" @click="done()">
          返回首页({{ countdown }})
        </van-button>
      </footer>
    </template>
    <template v-else>
      <header class="flex flex-col justify-center px-24" style="flex: 1 1 20%">
        <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>
        <div>w: {{ area.width }}, h: {{ area.height }}, m: {{ area.multiple }}</div>
      </header>
      <main class="relative flex justify-center items-center" style="flex: 1 1 40%">
        <Camera ref="camera" v-model:width="area.width" v-model:height="area.height" v-model:multiple="area.multiple">
          <template #default="{style, offsetX, offsetY}">
            <component :is="config?.shade" :style="style" :translateX="offsetX" :translateY="offsetY"></component>
            <img
              v-if="showExample"
              class="example"
              :style="{ opacity: transparency, ...style }"
              :src="config?.example"
              alt="示例"
              @click="showExample = false"
            />
          </template>
        </Camera>
        <div
          v-if="config?.example"
          class="size-40 absolute top-4 right-4 cursor-pointer hover:text-primary"
          @click="(showExample = !showExample) && (transparency = 1)"
        >
          <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 justify-evenly items-center" style="flex: 1 1 20%">
        <template v-if="config?.type === 'after'">
          <div class="cursor-pointer">
            <img class="h-20" src="@/assets/images/button-cancel.png" alt="重拍" @click="onCancel()" /></div>
          <div class="cursor-pointer">
            <img class="h-20" src="@/assets/images/button-confirm.png" alt="确认" @click="onConfirm()" />
          </div>
        </template>
        <div v-else-if="config?.type === 'before'" class="h-min cursor-pointer hover:text-primary" @click="onStart()">
          <button class="size-28 border-8 rounded-full hover:border-primary"></button>
          <div class="mt-8 text-3xl">{{ showExample && transparency === 1 ? '开始拍照' : '点击拍照' }}</div>
        </div>
      </footer>
    </template>
  </div>
</template>
<style scoped lang="scss">
.required {
  &::before {
    content: "*";
    margin-right: 4px;
    color: #f53030;
  }
}

header, footer {
  position: relative;
  z-index: 11;
}
</style>
