<template>
  <div>
    <DefaultHeaderPage
      :title="
        isEdit
          ? 'Editar Usuário'
          : 'Cadastro de Usuário'
      "
    />

    <div class="q-pa-md">
      <DefaultForm
        ref="formRef"
        @submit="onSave"
      >
        <div class="column items-center q-mb-lg">
          <AvatarImageComponent
            ref="avatarRef"
            @update:file="avatarFile = $event"
          />
        </div>

        <div class="row q-col-gutter-sm">
          <DefaultInput
            v-model="form.name"
            class="col-6"
            label="Nome completo"
            outlined
            :error="!!validationErrors.name"
            :error-message="validationErrors.name"
            :rules="[inputRules.required]"
          />

          <DefaultInput
            v-model="form.cpf"
            class="col-6"
            label="CPF"
            outlined
            :error="!!validationErrors.cpf"
            :error-message="validationErrors.cpf"
            :mask="masks.Brasil.cpf"
            :rules="[inputRules.cpf]"
          />

          <UserTypeSelect
            v-model="form.user_type"
            class="col-6"
            label="Função"
            outlined
            :disable="!canChangeUserType"
            :error="!!validationErrors.user_type"
            :error-message="validationErrors.user_type"
            :exclude-types="['ADMIN']"
            :rules="[inputRules.required]"
          />

          <DefaultInput
            v-model="form.phone"
            class="col-6"
            label="Telefone"
            outlined
            :error="!!validationErrors.phone"
            :error-message="validationErrors.phone"
            :mask="masks.Brasil.celular"
          />

          <DefaultInput
            v-model="form.email"
            class="col-6"
            label="E-mail"
            outlined
            type="email"
            :error="!!validationErrors.email"
            :error-message="validationErrors.email"
            :rules="[
              inputRules.required,
              inputRules.email,
            ]"
          />

          <DefaultPasswordInput
            v-model="form.password"
            class="col-6"
            label="Senha"
            outlined
            :error="!!validationErrors.password"
            :error-message="validationErrors.password"
            :rules="
              isEdit
                ? [
                    (value) =>
                      !value ||
                      value.length >= 8 ||
                      'Mínimo 8 caracteres',
                  ]
                : [
                    inputRules.required,
                    inputRules.min(8),
                  ]
            "
          />

          <div
            v-if="isEdit"
            class="col-12 text-caption text-grey-6"
          >
            Deixe os campos de senha em branco para manter a senha atual.
          </div>
        </div>

        <div class="row justify-end q-mt-lg q-gutter-sm">
          <q-btn
            color="primary"
            label="Cancelar"
            no-caps
            outline
            @click="router.push({ name: 'UsersPage' })"
          />

          <q-btn
            v-if="canSave"
            color="primary"
            label="Salvar"
            no-caps
            type="submit"
            :loading="loading"
          />
        </div>
      </DefaultForm>
    </div>
  </div>
</template>

<script setup>
import {
  computed,
  onMounted,
  ref,
} from "vue";

import {
  createUser,
  getUserById,
  updateUser,
} from "src/api/user";

import { permissionStore } from "src/stores/permission";
import { storeToRefs } from "pinia";
import { useForm } from "src/composables/useForm";
import { useInputRules } from "src/composables/useInputRules";
import { useQuasar } from "quasar";

import {
  useRoute,
  useRouter,
} from "vue-router";

import { useSubmitHandler } from "src/composables/useSubmitHandler";
import { userStore } from "src/stores/user";

import masks from "src/helpers/masks";

import AvatarImageComponent from "src/components/shared/AvatarImageComponent.vue";

import UserTypeSelect from "src/components/selects/UserTypeSelect.vue";

import DefaultForm from "src/components/defaults/DefaultForm.vue";
import DefaultInput from "src/components/defaults/DefaultInput.vue";
import DefaultPasswordInput from "src/components/defaults/DefaultPasswordInput.vue";
import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";

const $q = useQuasar();
const route = useRoute();
const router = useRouter();

const { inputRules } = useInputRules();

const permissions = permissionStore();
const store = userStore();

const { user } = storeToRefs(store);

const avatarRef = ref(null);
const formRef = ref(null);

const avatarFile = ref(null);
const originalUserType = ref(null);

const canChangeUserType = computed(
  () =>
    user.value?.user_type === "ADMIN_FRANCHISEE",
);

const canSave = computed(() =>
  permissions.getAccess(
    "franchisee_users",
    isEdit.value ? "edit" : "add",
  ),
);

const isEditingSelf = computed(
  () =>
    isEdit.value &&
    Number.parseInt(route.params.id) ===
      user.value?.id,
);

const isEdit = computed(
  () => !!route.params.id,
);

const {
  form,
  getUpdatedFields,
  setUpdateFormAsOriginal,
} = useForm({
  cpf: null,
  email: null,
  name: null,
  password: null,
  phone: null,
  user_type: null,
});

const {
  loading,
  validationErrors,
  execute,
} = useSubmitHandler({
  formRef,
  onSuccess: () => {
    router.push({
      name: "UsersPage",
    });
  },
});

const buildPayload = () => {
  const formData = new FormData();

  if (avatarFile.value) {
    formData.append(
      "avatar",
      avatarFile.value,
    );
  }

  if (store.selectedUnit?.id) {
    formData.append(
      "unit_id",
      store.selectedUnit.id,
    );
  }

  if (form.cpf) {
    formData.append("cpf", form.cpf);
  }

  if (form.email) {
    formData.append("email", form.email);
  }

  if (form.name) {
    formData.append("name", form.name);
  }

  if (form.password) {
    formData.append(
      "password",
      form.password,
    );
  }

  if (form.phone) {
    formData.append("phone", form.phone);
  }

  if (form.user_type) {
    formData.append(
      "user_type",
      form.user_type,
    );
  }

  return formData;
};

const onSave = async () => {
  if (
    isEditingSelf.value &&
    form.user_type !== originalUserType.value
  ) {
    $q.notify({
      message:
        "Não é possível alterar o seu próprio tipo de usuário. Entre em contato com o suporte.",
      type: "warning",
    });

    return;
  }

  if (!isEdit.value) {
    await execute(() =>
      createUser(buildPayload()),
    );

    return;
  }

  await execute(() => {
    const changedFields = {
      ...getUpdatedFields.value,
    };

    const formData = new FormData();

    for (const [key, value] of Object.entries(
      changedFields,
    )) {
      if (
        value !== null &&
        value !== undefined &&
        value !== ""
      ) {
        formData.append(key, value);
      }
    }

    if (avatarFile.value) {
      formData.append(
        "avatar",
        avatarFile.value,
      );
    }

    return updateUser(
      formData,
      route.params.id,
    );
  });
};

onMounted(async () => {
  if (!isEdit.value) return;

  try {
    const data = await getUserById(
      route.params.id,
    );

    form.cpf = data.cpf;
    form.email = data.email;
    form.name = data.name;
    form.phone = data.phone;
    form.user_type = data.user_type;

    originalUserType.value = data.user_type;

    setUpdateFormAsOriginal();

    if (data.avatar_url) {
      avatarRef.value?.setImageUrl(
        data.avatar_url,
      );
    }
  } catch (error) {
    console.error(
      "Failed to load user:",
      error,
    );
  }
});
</script>