<template>
  <q-card-section class="no-padding">
    <div class="column items-center q-gutter-y-xl q-pt-md">
      <div class="column items-center q-gutter-y-sm">
        <div
          :ref="fieldRefs.selfie"
          class="photo-circle"
          :class="selfieDone ? 'photo-circle--done' : 'photo-circle--pending'"
          @click="takeSelfie"
        >
          <img
            v-if="selfiePreviewUrl"
            class="photo-circle__thumb"
            :src="selfiePreviewUrl"
          />

          <q-icon
            v-else
            color="white"
            name="photo_camera"
            size="52px"
          />
        </div>

        <div
          v-if="serverErrors.selfie"
          class="text-negative font12 text-center"
        >
          {{ serverErrors.selfie }}
        </div>

        <template v-if="!selfieDone">
          <q-btn
            color="primary-button"
            no-caps
            padding="10px 28px"
            rounded
            :label="t('provider.login.steps.step_4.btn_selfie')"
            :loading="loadingSelfie"
            @click="takeSelfie"
          />

          <div class="font12 text-center text-text">
            {{ t('provider.login.steps.step_4.selfie_hint') }}
          </div>
        </template>

        <template v-else>
          <div class="items-center q-gutter-x-xs row">
            <q-icon
              color="positive"
              name="check_circle"
              size="18px"
            />

            <span class="text-primary">
              {{ t('provider.login.steps.step_4.selfie_sent') }}
            </span>
          </div>
        </template>
      </div>

      <div class="column items-center q-gutter-y-sm">
        <div
          :ref="fieldRefs.document_front"
          class="cursor-pointer"
          @click="openDocSubStep"
        >
          <div
            v-if="docDone"
            class="row items-center justify-center q-gutter-x-sm"
          >
            <div class="photo-circle photo-circle--small photo-circle--done">
              <img
                v-if="documentFrontPreviewUrl"
                class="photo-circle__thumb"
                :src="documentFrontPreviewUrl"
              />
            </div>

            <div class="photo-circle photo-circle--small photo-circle--done">
              <img
                v-if="documentBackPreviewUrl"
                class="photo-circle__thumb"
                :src="documentBackPreviewUrl"
              />
            </div>
          </div>

          <div
            v-else
            class="photo-circle photo-circle--pending"
          >
            <q-icon
              color="white"
              name="mdi-card-account-details-outline"
              size="52px"
            />
          </div>
        </div>

        <div
          v-if="serverErrors.document_front"
          class="text-negative font12 text-center"
        >
          {{ serverErrors.document_front }}
        </div>

        <div
          v-if="serverErrors.document_back"
          :ref="fieldRefs.document_back"
          class="text-negative font12 text-center"
        >
          {{ serverErrors.document_back }}
        </div>

        <template v-if="!docDone">
          <q-btn
            color="primary-button"
            no-caps
            padding="10px 28px"
            rounded
            :label="t('provider.login.steps.step_4.btn_document')"
            @click="openDocSubStep"
          />

          <div class="font12 text-center text-text">
            {{ t('provider.login.steps.step_4.document_hint') }}
          </div>
        </template>

        <template v-else>
          <div class="items-center q-gutter-x-xs row">
            <q-icon
              color="positive"
              name="check_circle"
              size="18px"
            />

            <span class="text-primary">
              {{ t('provider.login.steps.step_4.document_sent') }}
            </span>
          </div>
        </template>
      </div>
    </div>

    <Teleport to="body">
      <div
        v-if="showResult"
        class="fs-overlay"
      >
        <div class="fs-result">
          <q-img
            class="q-mb-xl"
            style="max-width: 150px"
            :src="LogoDiaria"
          />

          <div
            class="result-circle"
            :class="resultError ? 'result-circle--error' : 'result-circle--done'"
          >
            <q-icon
              color="white"
              size="56px"
              :name="resultIcon"
            />
          </div>

          <template v-if="resultError">
            <q-icon
              class="q-mt-md"
              color="negative"
              name="cancel"
              size="28px"
            />

            <div class="font14 q-mt-xs q-px-lg text-center text-primary">
              {{ t('provider.login.steps.step_4.error_message') }}
            </div>
          </template>

          <div
            v-else
            class="font14 q-mt-md q-px-lg text-center text-primary"
          >
            {{ resultMessage }}
          </div>

          <q-btn
            class="q-mt-xl"
            color="primary-button"
            no-caps
            padding="14px 48px"
            rounded
            style="min-width: 200px"
            :label="resultError
              ? t('provider.login.steps.step_4.btn_retry')
              : t('provider.login.steps.step_4.btn_continue')"
            @click="closeResult"
          />
        </div>
      </div>
    </Teleport>

    <Teleport to="body">
      <div
        v-if="showDocSubStep"
        class="fs-overlay doc-substep"
      >
        <div class="doc-substep__header">
          <q-btn
            flat
            icon="arrow_back"
            round
            @click="closeDocSubStep"
          />
        </div>

        <div class="doc-substep__body column items-center q-gutter-y-lg">
          <div class="doc-slot column items-center q-gutter-y-sm">
            <div class="text-primary">
              {{ t('provider.login.steps.step_4.document_front') }}
            </div>

            <div class="font12 text-center text-text">
              {{ t('provider.login.steps.step_4.document_front_desc') }}
            </div>

            <div
              class="doc-slot__preview"
              :class="docFrontDraft ? 'doc-slot__preview--done' : 'doc-slot__preview--pending'"
            >
              <q-img
                v-if="docFrontDraft"
                class="doc-slot__thumb"
                :src="docFrontPreviewUrl"
              />

              <q-icon
                v-else
                color="white"
                name="mdi-card-account-details-outline"
                size="48px"
              />
            </div>

            <div
              v-if="docFrontDraft"
              class="items-center q-gutter-x-xs row"
            >
              <q-icon
                color="positive"
                name="check_circle"
                size="16px"
              />

              <span class="font12 text-primary">
                {{ t('provider.login.steps.step_4.photo_captured') }}
              </span>
            </div>

            <div
              v-if="docFrontError"
              class="text-negative font12 text-center"
            >
              {{ t('provider.login.steps.step_4.error_message') }}
            </div>

            <q-btn
              color="primary-button"
              no-caps
              padding="8px 22px"
              rounded
              :label="docFrontDraft
                ? t('provider.login.steps.step_4.btn_retake')
                : t('provider.login.steps.step_4.btn_capture_front')"
              :loading="loadingDocFront"
              @click="captureDocFront"
            />
          </div>

          <div class="doc-slot column items-center q-gutter-y-sm">
            <div class="text-primary">
              {{ t('provider.login.steps.step_4.document_back') }}
            </div>

            <div class="font12 text-center text-text">
              {{ t('provider.login.steps.step_4.document_back_desc') }}
            </div>

            <div
              class="doc-slot__preview"
              :class="docBackDraft ? 'doc-slot__preview--done' : 'doc-slot__preview--pending'"
            >
              <q-img
                v-if="docBackDraft"
                class="doc-slot__thumb"
                :src="docBackPreviewUrl"
              />

              <q-icon
                v-else
                color="white"
                name="mdi-card-account-details-outline"
                size="48px"
              />
            </div>

            <div
              v-if="docBackDraft"
              class="items-center q-gutter-x-xs row"
            >
              <q-icon
                color="positive"
                name="check_circle"
                size="16px"
              />

              <span class="font12 text-primary">
                {{ t('provider.login.steps.step_4.photo_captured') }}
              </span>
            </div>

            <div
              v-if="docBackError"
              class="text-negative font12 text-center"
            >
              {{ t('provider.login.steps.step_4.error_message') }}
            </div>

            <q-btn
              color="primary-button"
              no-caps
              padding="8px 22px"
              rounded
              :label="docBackDraft
                ? t('provider.login.steps.step_4.btn_retake')
                : t('provider.login.steps.step_4.btn_capture_back')"
              :loading="loadingDocBack"
              @click="captureDocBack"
            />
          </div>
        </div>

        <div class="doc-substep__footer">
          <q-btn
            v-if="docSubStepDone"
            color="primary-button"
            no-caps
            padding="14px 48px"
            rounded
            style="min-width: 200px"
            :label="t('provider.login.steps.step_4.btn_continue')"
            @click="confirmDocCapture"
          />

          <div
            v-else
            class="font12 text-center text-grey-6"
          >
            {{ t('provider.login.steps.step_4.upload_all_photos') }}
          </div>
        </div>
      </div>
    </Teleport>
  </q-card-section>
</template>

<script setup>
import {
  Camera,
  CameraDirection,
  CameraResultType,
  CameraSource,
} from '@capacitor/camera';
import {
  computed, inject, onBeforeUnmount, ref, watch,
} from 'vue';
import { useI18n } from 'vue-i18n';

import LogoDiaria from 'src/assets/logo_diaria_campos_login.svg';

const emit = defineEmits(['update:show-sub-step']);

const form = defineModel({
  required: true,
  type: Object,
});

const { t } = useI18n();

const serverErrors = inject("serverErrors", ref({}));

const fieldRefs = {
  selfie: ref(null),
  document_front: ref(null),
  document_back: ref(null),
};

defineExpose({
  getFieldRef: (field) => fieldRefs[field] ?? null,
});

const loadingSelfie = ref(false);
const resultError = ref(false);
const resultIcon = ref('photo_camera');
const resultMessage = ref('');
const showResult = ref(false);

const showDocSubStep = ref(false);
const docFrontDraft = ref(null);
const docBackDraft = ref(null);
const docFrontPreviewUrl = ref(null);
const docBackPreviewUrl = ref(null);
const loadingDocFront = ref(false);
const loadingDocBack = ref(false);
const docFrontError = ref(false);
const docBackError = ref(false);

const selfiePreviewUrl = ref(null);
const documentFrontPreviewUrl = ref(null);
const documentBackPreviewUrl = ref(null);

const docDone = computed(() => (
  !!form.value.document_back
  && !!form.value.document_front
));

const docSubStepDone = computed(() => (
  !!docFrontDraft.value
  && !!docBackDraft.value
));

const selfieDone = computed(() => !!form.value.selfie);

const syncPreviewUrl = (previewRef, file) => {
  if (previewRef.value) {
    URL.revokeObjectURL(previewRef.value);
  }

  previewRef.value = file ? URL.createObjectURL(file) : null;
};

watch(() => form.value.selfie, (file) => syncPreviewUrl(selfiePreviewUrl, file), { immediate: true });
watch(() => form.value.document_front, (file) => syncPreviewUrl(documentFrontPreviewUrl, file), { immediate: true });
watch(() => form.value.document_back, (file) => syncPreviewUrl(documentBackPreviewUrl, file), { immediate: true });

const base64ToFile = (base64, filename, mimeType = 'image/jpeg') => {
  const byteString = atob(base64);
  const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(ab);

  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }

  return new File([ab], filename, {
    type: mimeType,
  });
};

const closeResult = () => {
  showResult.value = false;

  emit('update:show-sub-step', false);

  if (resultError.value) {
    resultError.value = false;
  }
};

const openCamera = async (direction) => {
  const photo = await Camera.getPhoto({
    allowEditing: false,
    direction: direction === 'front'
      ? CameraDirection.Front
      : CameraDirection.Rear,
    quality: 85,
    resultType: CameraResultType.Base64,
    saveToGallery: false,
    source: CameraSource.Camera,
  });

  return base64ToFile(
    photo.base64String.replace(/\s/g, ''),
    'photo.jpg',
    `image/${photo.format}`,
  );
};

const setDraftFile = (side, file) => {
  const draftRef = side === 'front' ? docFrontDraft : docBackDraft;
  const previewRef = side === 'front' ? docFrontPreviewUrl : docBackPreviewUrl;

  draftRef.value = file;
  syncPreviewUrl(previewRef, file);
};

const captureDocSide = async (side) => {
  const loadingRef = side === 'front' ? loadingDocFront : loadingDocBack;
  const errorRef = side === 'front' ? docFrontError : docBackError;

  if (loadingRef.value) {
    return;
  }

  loadingRef.value = true;
  errorRef.value = false;

  try {
    const file = await openCamera('rear');

    setDraftFile(side, file);
  } catch (err) {
    const msg = (err?.message || '').toLowerCase();

    if (
      !msg.includes('cancel')
      && !msg.includes('dismiss')
      && !msg.includes('no image')
    ) {
      errorRef.value = true;
    }
  } finally {
    loadingRef.value = false;
  }
};

const captureDocFront = () => captureDocSide('front');
const captureDocBack = () => captureDocSide('back');

const openDocSubStep = () => {
  if (!docFrontDraft.value && form.value.document_front) {
    setDraftFile('front', form.value.document_front);
  }

  if (!docBackDraft.value && form.value.document_back) {
    setDraftFile('back', form.value.document_back);
  }

  docFrontError.value = false;
  docBackError.value = false;
  showDocSubStep.value = true;

  emit('update:show-sub-step', true);
};

const closeDocSubStep = () => {
  showDocSubStep.value = false;

  emit('update:show-sub-step', false);
};

const confirmDocCapture = () => {
  if (!docSubStepDone.value) {
    return;
  }

  form.value.document_front = docFrontDraft.value;
  form.value.document_back = docBackDraft.value;
  showDocSubStep.value = false;

  emit('update:show-sub-step', false);
};

onBeforeUnmount(() => {
  [
    docFrontPreviewUrl,
    docBackPreviewUrl,
    selfiePreviewUrl,
    documentFrontPreviewUrl,
    documentBackPreviewUrl,
  ].forEach((previewRef) => {
    if (previewRef.value) {
      URL.revokeObjectURL(previewRef.value);
    }
  });
});

const takeSelfie = async () => {
  if (loadingSelfie.value) {
    return;
  }

  loadingSelfie.value = true;

  try {
    const file = await openCamera('front');

    form.value.selfie = file;
    resultError.value = false;
    resultIcon.value = 'photo_camera';
    resultMessage.value = t('provider.login.steps.step_4.selfie_success');
    showResult.value = true;

    emit('update:show-sub-step', true);
  } catch (err) {
    const msg = (err?.message || '').toLowerCase();

    if (
      !msg.includes('cancel')
      && !msg.includes('dismiss')
      && !msg.includes('no image')
    ) {
      resultError.value = true;
      resultIcon.value = 'photo_camera';
      showResult.value = true;

      emit('update:show-sub-step', true);
    }
  } finally {
    loadingSelfie.value = false;
  }
};
</script>

<style lang="scss" scoped>
.photo-circle {
  width: 130px;
  height: 130px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.15s ease;

  &:active {
    transform: scale(0.95);
  }

  &--done {
    background: linear-gradient(-90deg, #ec48d1 5%, #6b11cb 65%, #2574fc 100%);
  }

  &--pending {
    background-color: rgba(139, 92, 246, 0.18);
  }

  &--small {
    width: 90px;
    height: 90px;
  }
}

.photo-circle__thumb {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.fs-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: white;
}

.fs-result {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 28px;
  background: white;
}

.result-circle {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;

  &--done {
    background: linear-gradient(-90deg, #ec48d1 5%, #6b11cb 65%, #2574fc 100%);
  }

  &--error {
    background-color: rgba(139, 92, 246, 0.18);
  }
}

.doc-substep {
  display: flex;
  flex-direction: column;

  &__header {
    padding: 12px;
  }

  &__body {
    flex: 1;
    padding: 0 24px;
    overflow-y: auto;
  }

  &__footer {
    padding: 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
}

.doc-slot__preview {
  width: 160px;
  height: 110px;
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;

  &--pending {
    background-color: rgba(139, 92, 246, 0.18);
  }

  &--done {
    background: linear-gradient(-90deg, #ec48d1 5%, #6b11cb 65%, #2574fc 100%);
  }
}

.doc-slot__thumb {
  width: 100%;
  height: 100%;
}
</style>
