<script setup lang="ts">
import Drawer from "primevue/drawer";
import InputText from "primevue/inputtext";
import DatePicker from "primevue/datepicker";
import FloatLabel from "primevue/floatlabel";
import InputNumber from "primevue/inputnumber";
import Button from "primevue/button";
import {ref, onMounted, computed} from 'vue';
import {Transaction, TransactionType} from "@/models/Transaction";
import {CategoryType} from "@/models/Category";
import SelectButton from "primevue/selectbutton";
import Select from "primevue/select";
import platform from 'platform';
import {
  createTransactionRequest,
  getTransactionTypes,
  updateTransactionRequest,
  deleteTransactionRequest
} from "@/services/transactionService";
import {getCategories, getCategoryTypes} from "@/services/categoryService";
import {useToast} from "primevue/usetoast";
import LoadingView from "@/components/LoadingView.vue";

const props = defineProps({
  visible: {
    type: Boolean,
    required: true,
  },
  transaction: {
    type: Object as () => Transaction,
    required: false
  },
  transactionType: {
    type: String,
    required: false
  },
  categoryType: {
    type: String,
    required: false
  }
});

const emit = defineEmits(['create-transaction', 'update-transaction', 'delete-transaction', 'close-drawer', 'transaction-updated']);
const toast = useToast();
const categoryTypeChanged = () => {

  editedTransaction.value.category = selectedCategoryType.value.code == "EXPENSE" ? expenseCategories.value[0] : incomeCategories.value[0];

}
const selectCategory = (category) => {
  isCategorySelectorOpened.value = false;
  editedTransaction.value.category = category;
};


// Состояние
const loading = ref(false);
const isEditing = ref(!!props.transaction);
const isCategorySelectorOpened = ref(false);
const editedTransaction = ref<Transaction | null>(null);

const selectedCategoryType = ref<CategoryType | null>(null);
const selectedTransactionType = ref<TransactionType | null>(null);

const entireCategories = ref<Category[]>([]);
const expenseCategories = ref<Category[]>([]);
const incomeCategories = ref<Category[]>([]);
const categoryTypes = ref<CategoryType[]>([]);
const transactionTypes = ref<TransactionType[]>([]);

// Получение категорий и типов транзакций
const fetchCategoriesAndTypes = async () => {
  try {
    const [categoriesResponse, categoryTypesResponse, transactionTypesResponse] = await Promise.all([
      getCategories(),
      getCategoryTypes(),
      getTransactionTypes()
    ]);
    entireCategories.value = categoriesResponse.data;
    expenseCategories.value = categoriesResponse.data.filter((category: Category) => category.type.code === 'EXPENSE');
    incomeCategories.value = categoriesResponse.data.filter((category: Category) => category.type.code === 'INCOME');

    categoryTypes.value = categoryTypesResponse.data;
    transactionTypes.value = transactionTypesResponse.data;
  } catch (error) {
    console.error('Error fetching categories and types:', error);
  }
};

const checkForm = () => {
  const errorMessages = {
    transactionType: 'Тип транзакции должен быть выбран',
    category: 'Категория должна быть выбрана',
    date: 'Дата должна быть выбрана',
    comment: 'Комментарий должен быть введен',
    amount: 'Сумма не может быть пустой или 0'
  };

  if (!editedTransaction.value.transactionType) return showError(errorMessages.transactionType);
  if (!editedTransaction.value.category) return showError(errorMessages.category);
  if (!editedTransaction.value.date) return showError(errorMessages.date);
  if (!editedTransaction.value.comment) return showError(errorMessages.comment);
  if (!editedTransaction.value.amount || editedTransaction.value.amount === 0) return showError(errorMessages.amount);

  return true;
};

// Инициализация данных
const prepareData = () => {
  if (!props.transaction) {
    editedTransaction.value = new Transaction();
    editedTransaction.value.transactionType = transactionTypes.value.find(type => type.code === props.transactionType) || transactionTypes.value[0];
    selectedCategoryType.value = categoryTypes.value.find(type => type.code === props.categoryType) || categoryTypes.value[0];
    editedTransaction.value.category = props.categoryType === 'EXPENSE' ? expenseCategories.value[0] : incomeCategories.value[0];
    editedTransaction.value.date = new Date();
  } else {
    editedTransaction.value = {...props.transaction};
    selectedCategoryType.value = editedTransaction.value.category.type;
    selectedTransactionType.value = editedTransaction.value.transactionType;
  }

};
const result = ref(false)
const isError = ref(false)
const resultText = ref('')

const computeResult = (resultState, error) => {

  if (!resultState && error) {
    result.value = true;
    isError.value = true
    resultText.value = `Ошибка: ${error.message}`
  } else {

    result.value = true;
    isError.value = false
    resultText.value = 'Успех!'
  }
  setTimeout(() => {
    result.value = false
    resultText.value = ''
  }, 1000)
}

const showError = (message) => {
  result.value = true;
  isError.value = true;
  resultText.value = message;
  return false;
};

// Создание транзакции
const createTransaction = async () => {
  if (checkForm()) {
    try {
      loading.value = true;
      if (editedTransaction.value.transactionType.code === 'INSTANT') {
        editedTransaction.value.isDone = true;
      }
      await createTransactionRequest(editedTransaction.value);
      toast.add({severity: 'success', summary: 'Transaction created!', detail: 'Транзакция создана!', life: 3000});
      emit('create-transaction', editedTransaction.value);
      computeResult(true)
      resetForm();
    } catch (error) {
      computeResult(false, error)
      console.error('Error creating transaction:', error);
    } finally {
      loading.value = false;
    }
  }
  setTimeout(() => {
    result.value = false
    resultText.value = ''
  }, 1000)
};

// Обновление транзакции
const updateTransaction = async () => {
  if (checkForm()) {
    try {
      loading.value = true;
      const response = await updateTransactionRequest(editedTransaction.value);
      response.data;
      // toast.add({severity: 'success', summary: 'Transaction updated!', detail: 'Транзакция обновлена!', life: 3000});
      emit('update-transaction', editedTransaction.value);
      emit('transaction-updated');
      computeResult(true)
    } catch (error) {
      computeResult(false, error)
      console.error('Error updating transaction:', error);
    } finally {
      loading.value = false;
    }
  }
  setTimeout(() => {
    result.value = false
    resultText.value = ''

  }, 1000)
};

// Удаление транзакции
const deleteTransaction = async () => {
  try {
    loading.value = true;
    await deleteTransactionRequest(editedTransaction.value.id);
    toast.add({severity: 'success', summary: 'Transaction deleted!', detail: 'Транзакция удалена!', life: 3000});
    emit('delete-transaction', editedTransaction.value);
    closeDrawer()
    computeResult(true)
  } catch (error) {
    computeResult(false, error)
    toast.add({severity: 'warn', summary: 'Error!', detail: 'Транзакция обновлена!', life: 3000});

    console.error('Error deleting transaction:', error);
  } finally {
    loading.value = false;
  }
};

// Сброс формы
const resetForm = () => {

  editedTransaction.value.date = new Date();
  editedTransaction.value.amount = null;
  editedTransaction.value.comment = '';

};

const dateErrorMessage = computed(() => {

  if (editedTransaction.value.transactionType.code != 'PLANNED' && editedTransaction.value.date > new Date()) {

    return 'При мгновенных тратах дата должна быть меньше текущей!'
  } else if (editedTransaction.value.transactionType.code == 'PLANNED' && editedTransaction.value.date < new Date()) {

    return 'При плановых тратах дата должна быть больше текущей!'
  } else {

    return ''
  }
})

// Закрытие окна
const closeDrawer = () => emit('close-drawer');
const keyboardOpen = ref(false);
const isMobile = ref(false);
const userAgent = ref(null);
// Мониторинг при монтировании
onMounted(async () => {
  loading.value = true;

  await fetchCategoriesAndTypes();

  prepareData();

  loading.value = false;
  const deviceInfo = platform;
  isMobile.value = deviceInfo.os.family === 'iOS' || deviceInfo.os.family === 'Android';

})
</script>

<template>

  <div class="card flex justify-center h-dvh">


    <Drawer :visible="visible" :header="isEditing ? 'Edit Transaction' : 'Create Transaction'" :showCloseIcon="false"
            position="right" @hide="closeDrawer"
            class="!w-128  ">
      <div v-if="result" class="absolute top-0 left-0 w-full h-full flex items-center justify-center z-50">
        <div
            class=" px-10 py-5 rounded-lg  border border-gray-200  flex flex-col items-center gap-4"
            :class="isError ? 'bg-red-100' : 'bg-green-100'"
            aria-label="Custom ProgressSpinner">
          <i class="pi pi-check " :class="isError ? 'text-red-500' : 'text-green-500'" style="font-size: 2rem;"/>
          <p class="text-green-700" :class="isError ? 'text-red-500' : 'text-green-500'">{{ resultText }}</p>
        </div>

      </div>
      <div class="absolute w-full h-screen">
        <!-- Полупрозрачный белый фон -->
        <!--        <div class="absolute top-0 left-0 w-full h-full bg-white opacity-50 z-0"></div>-->

        <!-- Спиннер поверх -->

      </div>

      <LoadingView v-if="loading"/>
      <div v-else class=" grid gap-4 w-full ">

        <div class="relative w-full justify-center justify-items-center ">
          <div class="flex flex-col justify-items-center gap-2">
            <div class="flex flex-row gap-2">
              <!--            {{editedTransaction.value.transactionType}}-->
              <Select v-if="!isEditing" v-model="editedTransaction.transactionType" :allow-empty="false"
                      :options="transactionTypes"
                      optionLabel="name"
                      aria-labelledby="basic"
                      class="justify-center"/>
              <SelectButton v-model="selectedCategoryType" :options="categoryTypes" :allow-empty="false"
                            optionLabel="name"
                            aria-labelledby="basic"
                            @change="categoryTypeChanged" class="justify-center"/>
            </div>
            <button class="border border-gray-300 rounded-lg w-full z-40"
                    @click="isCategorySelectorOpened = !isCategorySelectorOpened">
              <div class="flex flex-row  items-center pe-4 py-2 ">
                <div class="flex flex-row justify-between w-full gap-4 px-4 items-center">
                  <p class="text-3xl font-bold text-gray-700 dark:text-gray-400">{{
                      editedTransaction.category.icon
                    }}</p>
                  <div class="flex flex-col items-start justify-items-start justify-around w-full">
                    <p class="font-bold text-start">{{ editedTransaction.category.name }}</p>
                    <p class="font-light line-clamp-1 items-start text-start">{{
                        editedTransaction.category.description
                      }}</p>
                  </div>
                </div>
                <div>
              <span :class="{'rotate-90': isCategorySelectorOpened}"
                    class="pi pi-angle-right transition-transform duration-300 text-5xl"/>
                </div>
              </div>
            </button>
          </div>

          <!-- Анимированное открытие списка категорий -->
          <div v-show="isCategorySelectorOpened"
               class="absolute left-0 right-0 top-full overflow-y-auto z-50 border-b-4 border-x  rounded-b-lg bg-white shadow-lg transition-all duration-500"
               :class="{ 'max-h-0': !isCategorySelectorOpened, 'max-h-[500px]': isCategorySelectorOpened }">
            <div class="grid grid-cols-2  mt-2">
              <button
                  v-for="category in editedTransaction.category.type.code == 'EXPENSE' ? expenseCategories : incomeCategories"
                  :key="category.id" class="border rounded-lg mx-2 mb-2"
                  @click="selectCategory(category)">
                <div class="flex flex-row justify-between w-full px-2">
                  <p class="text-4xl font-bold text-gray-700 dark:text-gray-400">{{ category.icon }}</p>
                  <div class="flex flex-col items-start justify-items-start justify-around w-full">
                    <p class="font-bold text-start">{{ category.name }}</p>
                    <p class="font-light line-clamp-1 text-start">{{ category.description }}</p>
                  </div>
                </div>
              </button>
            </div>
          </div>
        </div>
        <div class="flex flex-row gap-4">


          <FloatLabel variant="on" class="">
            <InputNumber class=""
                         :invalid="!editedTransaction.amount"
                         :minFractionDigits="0"
                         id="amount"
                         v-model="editedTransaction.amount"
                         mode="currency"
                         currency="RUB"
                         locale="ru-RU"
                         @focus="keyboardOpen=true"
                         @blur="keyboardOpen=false"

            />
            <label for="amount" class="">Amount</label>
          </FloatLabel>

          <!-- Comment Input -->

          <FloatLabel variant="on" class="w-full">
            <label for="comment">Comment</label>
            <InputText class="w-full"
                       :invalid="!editedTransaction.comment"
                       id="comment"
                       v-model="editedTransaction.comment"
                       @focus="keyboardOpen=true"
                       @blur="keyboardOpen=false"
            />
          </FloatLabel>

        </div>

        <!-- Date Picker -->
        <div class="field col-12 gap-0">
          <FloatLabel variant="on">
            <label for="date">Date </label>

            <DatePicker class="w-full"
                        inline
                        :invalid="editedTransaction.transactionType.code != 'PLANNED' ? editedTransaction.date > new Date() : true"
                        id="date"
                        v-model="editedTransaction.date"
                        dateFormat="yy-mm-dd"
                        showIcon

            />
            <p :class="dateErrorMessage != '' ? 'visible' : 'invisible'"
               class="text-red-400">{{ dateErrorMessage }}</p>


          </FloatLabel>
        </div>

        <!-- Amount Input -->


        <!-- Buttons -->
        {{ keyboardOpen }}
        <div class="fixed  col-12  flex justify-content-end gap-4 bottom-8">

          <Button label="Save" icon="pi pi-check" class="p-button-success"
                  @click="isEditing ? updateTransaction() : createTransaction()"/>
          <Button label="Cancel" icon="pi pi-times" class="p-button-secondary " @click="closeDrawer"/>
          <Button v-if="isEditing" label="Delete" icon="pi pi-times" class="p-button-success" severity="danger"
                  @click="deleteTransaction"/>
        </div>

      </div>
    </Drawer>
  </div>
</template>

<style scoped>

</style>
