<template>
  <q-scroll-area class="loyalty-suite-wrapper">
    <q-inner-loading :showing="loading">
      <q-spinner color="primary" size="70px" />
    </q-inner-loading>

    <template v-if="!loading">
      <div v-if="error" class="loyalty-suite-api-error-message">
        <q-icon name="error_outline" color="negative" size="md" />
        <span>{{ error }}</span>
      </div>

      <template v-else>
        <div class="loyalty-suite-wallet">
          <div class="loyalty-suite-wallet__title">
            <q-btn icon="arrow_back" color="primary" class="loyalty-suite-form__back" @click="goBack" />
            <h1 class="loyalty-suite-wallet__title-text">
              {{ isEditing ? $t('walletEdit') : $t('walletAdd') }}
            </h1>
          </div>
          <q-form class="loyalty-suite-form" @submit.prevent="submitForm">
            <div class="loyalty-suite-form__section">
              <div class="loyalty-suite-form__title">
                {{ $t('mainSettings') }}
              </div>

              <div class="loyalty-suite-form__row">
                <span class="loyalty-suite-form__row-label">
                  {{ $t('walletName') }}
                  <span class="loyalty-suite-form__row-label-required">*</span>
                  <q-icon name="info_outline" size="18px" class="loyalty-suite-form__row-hint">
                    <q-tooltip anchor="top right" self="top right">
                      {{ $t('walletNameHint') }}
                    </q-tooltip>
                  </q-icon>
                </span>
                <q-input v-model="wallet.name" outlined required
                  :rules="[(val: string) => val && val.length > 0 || $t('requiredField')]" />
              </div>

              <div class="loyalty-suite-form__row">
                <span class="loyalty-suite-form__row-label">
                  {{ $t('unitName') }}
                  <span class="loyalty-suite-form__row-label-required">*</span>
                  <q-icon name="info_outline" size="18px" class="loyalty-suite-form__row-hint">
                    <q-tooltip anchor="top right" self="top right">
                      {{ $t('unitNameHint') }}
                    </q-tooltip>
                  </q-icon>
                </span>
                <q-input v-model="wallet.unit_singular" outlined required
                  :rules="[(val: string) => val && val.length > 0 || $t('requiredField')]" />
              </div>

              <div class="loyalty-suite-form__row">
                <span class="loyalty-suite-form__row-label">
                  {{ $t('unitpluralName') }}
                  <span class="loyalty-suite-form__row-label-required">*</span>
                  <q-icon name="info_outline" size="18px" class="loyalty-suite-form__row-hint">
                    <q-tooltip anchor="top right" self="top right">
                      {{ $t('unitPluralNameHint') }}
                    </q-tooltip>
                  </q-icon>
                </span>
                <q-input v-model="wallet.unit_plural" outlined required
                  :rules="[(val: string) => val && val.length > 0 || $t('requiredField')]" />
              </div>

              <div class="loyalty-suite-form__row">
                <span class="loyalty-suite-form__row-label">
                  {{ $t('unitIcon') }}
                </span>
                <div class="loyalty-suite-form__preview"
                  :class="{ 'loyalty-suite-form__preview_empty': !wallet.unit_icon }" @click="openLibrary">
                  <div class="loyalty-suite-form__preview-container">
                    <img v-if="previewUrl" :src="previewUrl" class="loyalty-suite-form__preview-img" />
                    <q-btn v-if="wallet.unit_icon" icon="close" color="negative" @click.stop="removeIcon"
                      class="loyalty-suite-form__preview-remove" />
                    <q-icon v-else name="file_upload" class="loyalty-suite-form__preview-icon" />
                    <span v-if="previewName" class="loyalty-suite-form__preview-name">
                      {{ previewName }}
                    </span>
                    <span v-else class="loyalty-suite-form__preview-label">
                      {{ $t('fileUpload') }}
                    </span>
                  </div>
                </div>
              </div>

              <Library v-model="wallet.unit_icon" v-model:showLibrary="showLibrary" v-model:selectedTab="currentTab"
                @update:modelValue="setIcon" />

              <div class="loyalty-suite-form__row" :class="{ 'loyalty-suite-form__row-pro': !isPro }">
                <q-badge v-if="!isPro" color="positive" label="PRO" />
                <span class="loyalty-suite-form__row-label">
                  {{ $t('unitCashbackRate') }}
                  <q-icon name="info_outline" size="18px" class="loyalty-suite-form__row-hint">
                    <q-tooltip anchor="top right" self="top right">
                      {{ $t('unitCashbackRateHint') }}
                    </q-tooltip>
                  </q-icon>
                </span>
                <q-input
                  outlined
                  v-model="wallet.cashback_rate"
                  type="number"
                  :disable="!isPro"
                  :readonly="!isPro"
                  @update:model-value="() => { if (isPro) formatFloat('cashback_rate') }"
                />
              </div>

              <div class="loyalty-suite-form__row">
                <span class="loyalty-suite-form__row-label">
                  {{ $t('unitLimit') }}
                  <q-icon name="info_outline" size="18px" class="loyalty-suite-form__row-hint">
                    <q-tooltip anchor="top right" self="top right">
                      {{ $t('unitLimitHint') }}
                    </q-tooltip>
                  </q-icon>
                </span>
                <q-input v-model="wallet.units_limit" outlined type="number"
                  @update:model-value="formatFloat('units_limit')" />
              </div>

              <div class="loyalty-suite-form__row loyalty-suite-form__row_toggler">
                <q-toggle v-model="wallet.is_convertible" :label="$t('unitConvertible')" />
              </div>

              <div v-if="wallet.is_convertible" class="loyalty-suite-form__row">
                <span class="loyalty-suite-form__row-label">
                  {{ $t('unitConversionRate') }} 1{{ currency['symbol'] }}
                  <span class="loyalty-suite-form__row-label-required">*</span>
                  <q-icon name="info_outline" size="18px" class="loyalty-suite-form__row-hint">
                    <q-tooltip anchor="top right" self="top right">
                      {{ $t('unitConversionRateHint') }}
                    </q-tooltip>
                  </q-icon>
                </span>
                <q-input outlined v-model="wallet.conversion_rate" type="number" required
                  :rules="[(val: number | null) => val && val > 0 || $t('requiredField')]"
                  @update:model-value="formatFloat('conversion_rate')" />
                <div class="loyalty-suite-wallet__conversion" v-if="wallet.conversion_rate">
                  1{{ currency['symbol'] }} = {{ wallet.conversion_rate }}
                  {{ Number(wallet.conversion_rate) === 1 ? $t('unit') : $t('units') }}
                </div>
              </div>

              <div class="loyalty-suite-form__row loyalty-suite-form__row_toggler">
                <q-toggle v-model="wallet.active" :label="wallet.active ? $t('enabledWallet') : $t('disabledWallet')"
                  @update:model-value="confirmDeactivation" />
              </div>
            </div>

            <div class="loyalty-suite-form__action">
              <q-btn v-if="isEditing" class="loyalty-suite-form__action-delete" :label="$t('delete')"
                @click="confirmDelete = true" color="negative" :loading="changeLoading" />
              <q-btn type="submit" :label="isEditing ? $t('save') : $t('add')" :loading="changeLoading"
                color="primary" />
            </div>

            <div v-if="addError" class="loyalty-suite-form__action-error">
              {{ $t(addError) }}
            </div>

            <q-dialog v-model="Deactivate">
              <q-card>
                <q-card-section>
                  <span>{{ $t('walletDeactivation') }}</span>
                </q-card-section>
                <q-card-actions align="center">
                  <q-btn :label="$t('ok')" color="primary" :loading="changeLoading" v-close-popup />
                </q-card-actions>
              </q-card>
            </q-dialog>

            <q-dialog v-model="confirmDelete">
              <q-card>
                <q-card-section>
                  <span>{{ $t('walletDelete') }}</span>
                  <span>{{ $t('affectMembers') }}</span>
                </q-card-section>
                <q-card-actions align="center">
                  <q-btn :label="$t('cancel')" color="negative" v-close-popup />
                  <q-btn :label="$t('delete')" color="primary" @click="deleteWallet" />
                </q-card-actions>
              </q-card>
            </q-dialog>

            <q-dialog v-model="confirmLeave">
              <q-card>
                <q-card-section>
                  <span>{{ $t('unsavedChanges') }}</span>
                </q-card-section>
                <q-card-actions align="center">
                  <q-btn :label="$t('cancel')" color="negative" v-close-popup />
                  <q-btn :label="$t('discardChanges')" color="primary" v-close-popup @click="navigateBack" />
                </q-card-actions>
              </q-card>
            </q-dialog>
          </q-form>
        </div>
      </template>
    </template>
  </q-scroll-area>
</template>

<script lang="ts">
import { defineComponent, ref, onBeforeMount, computed, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import Library from '../../components/Library.vue';

export default defineComponent({
  components: { Library },
  setup() {
    const route = useRoute();
    const router = useRouter();
    const { t } = useI18n();
    const loading = ref(true);
    const changeLoading = ref(false);
    const originalWallet = ref<string | null>(null);
    const confirmLeave = ref(false);
    const confirmDelete = ref(false);
    const Deactivate = ref(false);
    const error = ref<string | null>(null);
    const addError = ref<string | null>(null);
    const fileError = ref<boolean | null>(null);
    const currency = ref({ symbol: '$' });
    const isPro = window.loyalty_suite_admin_data.isPro;
    const apiRoutes = window.loyalty_suite_admin_data.apiRoutes;
    const nonce = window.loyalty_suite_admin_data.nonce;
    const isEditing = computed(() => !!route.params.id);
    const previewUrl = ref<string | null>(null);
    const previewName = ref<string | null>(null);
    const showLibrary = ref(false);
    const currentTab = ref('coins');

    const wallet = ref<{
      id: number | null;
      name: string;
      unit_singular: string,
      unit_plural: string,
      unit_icon: File | null,
      units_limit: number | null,
      is_convertible: boolean,
      active: boolean,
      conversion_rate: number | null,
      cashback_rate: number | null,
    }>({
      id: !isNaN(Number(route.params.id)) ? Number(route.params.id) : null,
      name: '',
      unit_singular: '',
      unit_plural: '',
      unit_icon: null,
      units_limit: null,
      is_convertible: true,
      active: true,
      conversion_rate: null,
      cashback_rate: null,
    });

    const goBack = () => {
      if (isDirty.value) {
        confirmLeave.value = true;
        return;
      }

      navigateBack();
    };

    const navigateBack = () => {
      if (window.history.length > 1) {
        router.back();
      } else {
        router.push('/wallets/list');
      }
    };

    const isDirty = computed(() => {
      return JSON.stringify(wallet.value) !== originalWallet.value;
    });

    const removeIcon = () => {
      wallet.value.unit_icon = null;
      previewUrl.value = null;
      previewName.value = null;
    };

    const openLibrary = () => {
      if (!wallet.value.unit_icon) {
        showLibrary.value = true;
      }
    };

    const setIcon = (icon: File) => {
      wallet.value.unit_icon = icon;
      previewUrl.value = URL.createObjectURL(icon);
      previewName.value = icon.name;
    };

    const formatFloat = (field: keyof typeof wallet.value) => {
      if (['cashback_rate', 'units_limit', 'conversion_rate'].includes(field)) {
        const value = wallet.value[field];

        if (value === null || value === '' || isNaN(Number(value)) || Number(value) === 0) {
          wallet.value[field] = null as never;
          return;
        }

        wallet.value[field] = Number(value) as never;
      }
    };

    const confirmDeactivation = (value: boolean) => {
      if (!value) {
        Deactivate.value = true;
      }
    };

    const fetchCurrency = async () => {
      try {
        const response = await fetch(apiRoutes.admin.currency, {
          method: 'GET',
          headers: {
            'X-WP-Nonce': nonce,
            'Content-Type': 'application/json',
          }
        });

        if (!response.ok) {
          throw new Error(`API Error: ${response.status} ${response.statusText}`);
        }

        const data = await response.json();
        currency.value = data;
      } catch (err) {
        error.value = err instanceof Error ? err.message : t('couldNotFetchData');
        console.error('API Error:', error.value);
      }
    };

    const fetchWallet = async () => {
      if (!isEditing.value) return;

      try {
        const buildApiUrl = (base, params = {}) => {
          const url = new URL(base, window.location.origin);
          Object.entries(params).forEach(([key, value]) => {
            if (value !== undefined && value !== null && value !== '') {
              url.searchParams.set(key, value);
            }
          });
          return url.toString();
        };

        const response = await fetch(
          buildApiUrl(apiRoutes.admin.wallet, {
            id: Number(route.params.id),
          }),
          {
            method: 'GET',
            headers: {
              'X-WP-Nonce': nonce,
              'Content-Type': 'application/json',
            },
            credentials: 'same-origin',
          }
        );

        const data = await response.json().catch(() => null);

        if (!response.ok) {
          addError.value = data?.error;
          return;
        }

        currency.value = data.currency;
        wallet.value = {
          id: Number(route.params.id) ?? null,
          ...data.wallet,
        };
        previewUrl.value = data.wallet.unit_icon_preview;
        previewName.value = data.wallet.unit_icon_filename;
      } catch (err) {
        error.value = err instanceof Error ? err.message : t('couldNotFetchData');
        console.error('API Error:', error.value);
      }
    };

    const deleteWallet = async () => {
      try {
        changeLoading.value = true;
        const response = await fetch(apiRoutes.admin.wallet_delete, {
          method: 'DELETE',
          headers: {
            'Content-Type': 'application/json',
            'X-WP-Nonce': nonce
          },
          body: JSON.stringify({ id: Number(route.params.id) })
        });

        const responseData = await response.json().catch(() => null);

        if (!response.ok) {
          addError.value = responseData?.error;
          return;
        }

        router.push('/wallets/list');
      } catch (err) {
        error.value = err instanceof Error ? err.message : 'Error deleting wallet';
      } finally {
        changeLoading.value = false;
      }
    };

    const submitForm = async () => {
      if (!wallet.value.unit_singular || !wallet.value.unit_plural || !wallet.value.name) {
        return;
      }

      if (wallet.value.is_convertible && wallet.value.conversion_rate === null) {
        return;
      }

      if (!wallet.value.is_convertible) {
        wallet.value.conversion_rate = null;
      }

      try {
        changeLoading.value = true;
        const formData = new FormData();

        if (wallet.value.id !== null) {
          formData.append('id', String(wallet.value.id));
        }
        formData.append('name', wallet.value.name);
        formData.append('unit_singular', wallet.value.unit_singular);
        formData.append('unit_plural', wallet.value.unit_plural);
        formData.append('active', String(wallet.value.active));
        formData.append('is_convertible', String(wallet.value.is_convertible));

        if (wallet.value.conversion_rate !== null) {
          formData.append('conversion_rate', String(wallet.value.conversion_rate));
        }

        if (wallet.value.cashback_rate !== null) {
          formData.append('cashback_rate', String(wallet.value.cashback_rate));
        }

        if (wallet.value.units_limit !== null) {
          formData.append('units_limit', String(wallet.value.units_limit));
        }

        if (wallet.value.unit_icon) {
          formData.append('unit_icon', wallet.value.unit_icon);
        }

        const response = await fetch(apiRoutes.admin.wallet_save, {
          method: 'POST',
          headers: {
            'X-WP-Nonce': nonce
          },
          body: formData
        });

        const responseData = await response.json().catch(() => null);

        if (responseData.error) {
          addError.value = responseData?.error;
          return;
        }

        router.push('/wallets/list');
      } catch (err) {
        error.value = err instanceof Error ? err.message : 'Error submitting data';
      } finally {
        changeLoading.value = false;
      }
    };

    onBeforeMount(async () => {
      await Promise.all([fetchCurrency(), fetchWallet()]);
      loading.value = false;

      watch(wallet, (newVal) => {
        if (originalWallet.value === null) {
          originalWallet.value = isEditing.value
            ? JSON.stringify(newVal)
            : JSON.stringify({
              id: route.params.id ?? null,
              name: '',
              unit_singular: '',
              unit_plural: '',
              unit_icon: null,
              units_limit: null,
              is_convertible: true,
              active: true,
              conversion_rate: null,
              cashback_rate: null,
            });
        }
      }, { deep: true, immediate: true });
    });

    watch(() => route.params.id, fetchWallet);

    return {
      changeLoading,
      loading,
      error,
      addError,
      fileError,
      confirmLeave,
      navigateBack,
      previewUrl,
      previewName,
      currency,
      wallet,
      isEditing,
      formatFloat,
      confirmDelete,
      Deactivate,
      goBack,
      confirmDeactivation,
      deleteWallet,
      removeIcon,
      submitForm,
      showLibrary,
      openLibrary,
      currentTab,
      setIcon,
      isPro
    };
  }
});
</script>

<style lang="scss" scoped>
.loyalty-suite-wallet {
  display: flex;
  flex-direction: column;
  width: 100%;

  &__title {
    display: flex;
    align-items: center;
    width: 100%;
    margin-bottom: 25px;

    &-text {
      display: flex;
      font-size: 22px;
    }
  }

  &__conversion {
    display: flex;
    width: 100%;
    padding-top: 15px;
  }

  .loyalty-suite-form {
    width: 700px;
  }
}
</style>
