<template>
  <div
    v-if="data"
    :class="{'_loading': loading}"
    class="profile-setup"
  >
    <header
      :class="{'_loading': deletingAvatar}"
      class="profile-setup__header"
    >
      <div class="profile-setup__avatar-wrapper">
        <UiAvatar
          :src="avatarPreview"
          :size="112"
          class="profile-setup__avatar"
        />
        <label
          v-if="!data.avatar && !avatarPreview"
          :title="$t('add_avatar')"
          class="profile-setup__avatar-edit"
          for="avatar-edit"
        >
          <UiIcon
            name="photo-cam"
            size="18"
          />
          <input
            id="avatar-edit"
            class="_visually-hidden"
            type="file"
            accept=".jpg,.jpeg,.png,.webp,image/jpeg,image/png,image/webp"
            @change="onAvatarChange"
          >
        </label>
        <template v-else>
          <button
            v-if="data.avatar || form.avatar"
            :disabled="deletingAvatar"
            :aria-label="$t('delete_avatar')"
            class="profile-setup__avatar-edit --delete"
            @click="deleteAvatar"
          >
            <UiIcon
              name="close"
              size="20"
            />
          </button>
        </template>
      </div>
      <h1 class="profile-setup__title">{{ data.username }}</h1>
      <p class="profile-setup__members">
        {{ $t('member_since', { date: memberSince }) }}</p>
    </header>
    <div class="profile-setup__grid-edit">
      <UiInput
        v-model="form.email"
        :label="t('profile.email')"
        :placeholder="t('enter_email')"
        :error="error.email"
        type="email"
        label-icon="mail"
        class="profile-setup__email-edit"
        @update:error="val => error.email = val"
      />
      <UiSelect
        v-model="formCountry"
        :label="t('profile.country')"
        :label-icon="{ icon: 'geo' }"
        :placeholder="t('profile.country')"
        :items="countriesItems || []"
        name="country"
      />
      <UiInput
        v-model="form.city"
        :label="t('profile.city')"
        :placeholder="t('enter_city')"
        label-icon="geo"
      />
      <UiInput
        :label="t('profile.date_of_birth')"
        :model-value="fromUnix(form.birthday || 0)"
        class="profile-setup__item-date"
        type="date"
        label-icon="date"
        @update:model-value="(event: string) => setDate(event)"
      />
      <UiSelect
        v-model="formGender"
        :label-icon="{ icon: 'double-user' }"
        :label="t('profile.gender')"
        :placeholder="t('profile.gender')"
        :items="gendersItems || []"
        name="gender"
      />
    </div>
    <div class="profile-setup__history">
      <UiIcon
        class="profile-setup__history-icon"
        name="time"
        size="20"
      />
      <p class="profile-setup__history-text">{{ t('history_text')}}</p>
      <UiToggle
        left
        v-model="saveHistory"
      />
    </div>
    <div class="profile-setup__buttons">
      <UiBtn
        class="profile-setup__button"
        wide
        size="l"
        theme="secondary"
        @click="cancelEdit"
      >{{ t('profile.cancel') }}
      </UiBtn>
      <UiBtn
        class="profile-setup__button"
        wide
        size="l"
        theme="primary"
        @click="updateProfile"
      ><span class="_from-xs">{{ t('profile.update_profile') }}</span>
        <span class="_to-xs">{{ t('profile.update') }}</span>
      </UiBtn>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { ICountry, IGender, IProfileData, ISelectItem } from '../../types';
import { compressImage, convertDateToTimestamp, validateEmail } from '../../runtime';
import { AuthorizationApiService } from '../../services/api/authorization.service';
import { DictionariesApiService } from '../../services/api/dictionaries.service';

interface IProfileFormEdit {
  avatar: Blob | null | string,
  name: string
  email: string
  country: string | ICountry | null
  city: string
  birthday: number | null
  gender: string | IGender | null
}

const data = computed(() => useState<IProfileData>('profileData').value);

const { toUnix, fromUnix } = convertDateToTimestamp();
const {
  deleteAvatar: deleteAvatarUser,
  getProfile,
  changeEmail,
  updateProfile: updateProfileUser,
} = useUser(AuthorizationApiService);

const formCountry = ref<string>((data.value.country as any)?.title ?? data.value.country ?? '');
const formGender = ref<string>((data.value.gender as any)?.title ?? data.value.gender ?? '');
const saveHistory = ref(false);

const form = ref<IProfileFormEdit>({
  avatar: data.value.avatar as Blob | null | string,
  name: data.value.username,
  email: data.value.email,
  country: formCountry.value,
  city: data.value.city,
  birthday: data.value.birthday,
  gender: formGender.value,
});

const avatarPreview = ref('');

const { t, locale } = useI18n();
const { generateLink } = useGenerateLink();

const memberSince = computed(() => {
  if (!data.value?.created) return '';
  const date = new Date(data.value.created * 1000);
  return new Intl.DateTimeFormat(locale.value, { month: 'long', year: 'numeric' }).format(date);
});

const error = ref({
  email: false,
});

function setDate(string: string) {
  form.value.birthday = toUnix(string);
}

const deletingAvatar = ref(false);
const { show } = useSnackbar();

async function deleteAvatar() {
  deletingAvatar.value = true;
  try {
    await deleteAvatarUser();
    form.value.avatar = '';
    await getProfile(true);
    avatarPreview.value = '';
    show('avatar_deleted');
  } finally {
    deletingAvatar.value = false;
  }
}

function onAvatarChange(event: Event) {
  const target = event.target as HTMLInputElement;
  const files = target.files;

  if (!files || files.length === 0) return;

  const file = files[ 0 ];
  const blob = new Blob([file], { type: file.type });

  form.value.avatar = blob;

  avatarPreview.value = URL.createObjectURL(blob);
}

const [
  { countriesData },
  { gendersData },
] = await Promise.all([
  useFetchDictionariesCountries(DictionariesApiService.getCountries),
  useFetchDictionariesGenders(DictionariesApiService.getGenders),
]);

const countriesItems = computed<ISelectItem[] | undefined>(() => countriesData.value?.countries.map(item => ({
  title: item.title,
  value: item.title,
})));

const gendersItems = computed<ISelectItem[] | undefined>(() => gendersData.value?.genders.map(item => ({
  title: item.title,
  value: item.title,
})));

function findCountry() {
  return countriesData.value?.countries.find(item => item.title === formCountry.value);
}

function findGender() {
  return gendersData.value?.genders.find(item => item.title === formGender.value);
}

async function urlToBlob(url: string): Promise<Blob> {
  const response = await fetch(url);
  return await response.blob();
}

const loading = ref(false);

const updateProfile = async () => {
  form.value.country = findCountry() || null;
  form.value.gender = findGender() || null;

  error.value.email = false;

  if (!validateEmail(form.value.email)) {
    error.value.email = true;
    return;
  }

  try {
    loading.value = true;

    if (form.value.avatar instanceof Blob) {
      form.value.avatar = await compressImage(form.value.avatar, 512, 0.8);
    } else if (data.value.avatar) {
      form.value.avatar = await urlToBlob(data.value.avatar);
    }

    if (form.value.email !== data.value.email) {
      const value = {
        email: form.value.email
      };
      await changeEmail(value);
    }

    await updateProfileUser(form.value);
    await getProfile(true);
    navigateTo(generateLink('/user/profile'));
  } catch (error) {
    console.log('error update profile', error);
  } finally {
    loading.value = false;
  }
};

function cancelEdit() {
  navigateTo(generateLink('/user/profile'));
}
</script>

<style lang="scss">
.profile-setup {
  display: grid;
}

.profile-setup__title {
  @include font-xl;

  margin-top: 16px;
  font-weight: 700;
  text-transform: uppercase;
}

.profile-setup__members {
  @include font-sm;

  color: $setup-members-text;
}

.profile-setup__avatar.ui-avatar {
  @include font-4xl;
}

.profile-setup__button {
  height: 50px;
}

.profile-setup__avatar-wrapper {
  position: relative;
  width: max-content;
  margin: 0 auto;
}

.profile-setup__avatar-edit {
  $size: 40px;

  position: absolute;
  bottom: 0;
  right: 0;
  display: grid;
  place-content: center;
  width: $size;
  height: $size;
  background-color: $setup-avatar-edit-bg;
  border: 2px solid $setup-avatar-edit-border;
  border-radius: $radius-full;
  color: $setup-avatar-edit-text;

  @include from-br(sm) {
    cursor: pointer;
  }

  @include hover(background-color) {
    background-color: $setup-avatar-edit-bg--hover;
  }
}

.profile-setup__avatar-edit.--delete {
  background-color: $setup-delete-bg;
  color: $setup-delete-text;
  border: 2px solid $setup-delete-border;

  @include hover(background-color) {
    background-color: $setup-delete-bg--hover;
  }
}

.profile-setup__header {
  display: grid;
  justify-items: center;
  margin-bottom: 32px;
}

.profile-setup__grid-edit {
  display: grid;
  column-gap: 16px;
  row-gap: 24px;
  padding-top: 32px;
  margin-bottom: 32px;
  border-top: 1px solid $setup-border;

  @include from-br(xs) {
    grid-template-columns: 1fr 1fr;
  }
}

.profile-setup__email-edit {
  @include from-br(xs) {
    grid-column: 1/-1;
  }
}

.profile-setup__history {
  display: grid;
  column-gap: 12px;
  padding: 16px 0 8px;
  margin-bottom: 42px;
  border-top: 1px solid $setup-border;
  grid-template-columns: auto 1fr auto;
  align-items: center;
}

.profile-setup__history-icon {
  color: $setup-history-icon;
}

.profile-setup__history-text {
  @include font-sm;

  color: $setup-history-text;
}

.profile-setup__buttons {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 12px;
}
</style>
