<template>
  <q-dialog ref="dialogRef" @hide="onDialogHide">
    <q-card
      class="q-dialog-plugin dialog-form-card"
      :style="dialogCardStyle"
    >
      <DefaultDialogHeader
        :title="props.contract ? 'Editar Contrato' : 'Novo Contrato'"
        @close="onDialogCancel"
      />

      <template v-if="props.contract">
        <q-tabs
          v-model="activeTab"
          active-color="primary"
          align="left"
          class="q-px-md text-grey-7"
          dense
          indicator-color="primary"
        >
          <q-tab
            label="Dados do Contrato"
            name="dados"
          />

          <q-tab
            label="Mídias do Contrato"
            name="midias"
          />
        </q-tabs>

        <q-separator />
      </template>

      <DefaultForm
        ref="formRef"
        @submit="handleSave"
      >
        <q-scroll-area
          ref="scrollAreaRef"
          class="dialog-form-scroll"
        >
          <q-card-section class="q-pt-sm">
            <div v-show="activeTab === 'dados'">
              <DefaultInput
                :model-value="store.user?.name"
                class="q-mb-md"
                label="Franqueado operador"
                readonly
              />

              <div class="text-subtitle1 q-mb-md">
                Dados da Unidade
              </div>

              <div class="row q-col-gutter-sm">
                <DefaultInput
                  v-model:error="validationErrors.unit_id"
                  :model-value="unitDetails.name"
                  class="col-12 col-md-6"
                  label="Nome da Unidade"
                  readonly
                />

                <DefaultInput
                  v-model:error="validationErrors.unit_id"
                  :model-value="unitDetails.cnpj"
                  :mask="masks.Brasil.cnpj"
                  class="col-12 col-md-6"
                  label="CNPJ"
                  readonly
                />
              </div>

              <div class="text-subtitle1 q-mt-lg q-mb-md">
                Dados do Aluno
              </div>

              <div class="row q-col-gutter-sm">
                <div
                  v-if="props.selectStudent"
                  class="col-12"
                >
                  <div class="row items-start no-wrap q-col-gutter-sm">
                    <DefaultSelect
                      v-model="selectedStudent"
                      v-model:error="validationErrors.student_id"
                      class="col"
                      dropdown-icon="mdi-magnify"
                      fill-input
                      hide-selected
                      input-debounce="0"
                      label="Aluno"
                      option-label="name"
                      use-input
                      :options="filteredStudents"
                      :rules="[inputRules.required]"
                      @filter="filterStudents"
                    />

                    <div
                      v-if="canAddStudents"
                      class="col-auto"
                    >
                      <q-btn
                        aria-label="Cadastrar novo aluno"
                        color="primary"
                        icon="mdi-plus"
                        round
                        unelevated
                        @click="openCreateStudent"
                      >
                        <q-tooltip>
                          Cadastrar novo aluno
                        </q-tooltip>
                      </q-btn>
                    </div>
                  </div>
                </div>

                <div
                  v-if="!props.selectStudent"
                  class="col-12"
                >
                  <DefaultInput
                    v-model:error="validationErrors.student_id"
                    :model-value="currentStudent?.name"
                    :rules="[inputRules.required]"
                    disable
                    label="Aluno"
                  />
                </div>

                <div class="col-12">
                  <DefaultInput
                    v-model:error="validationErrors.birth_date"
                    :model-value="formattedBirthDate"
                    disable
                    label="Data de Nascimento"
                  />
                </div>
              </div>

              <div class="text-subtitle1 q-mt-lg q-mb-md">
                Dados do Contrato
              </div>

              <div class="row q-col-gutter-sm">
                <div class="col-4">
                  <DefaultInput
                    v-model="form.protocol"
                    v-model:error="validationErrors.protocol"
                    label="Protocolo"
                    :rules="[optionalMaxLengthRule(255)]"
                  />
                </div>

                <div class="col-4">
                  <DefaultInputDatePicker
                    v-model="form.signature_date"
                    v-model:error="validationErrors.signature_date"
                    label="Data Assinatura"
                    :rules="[optionalDateRule]"
                  />
                </div>

                <div class="col-4">
                  <DefaultInputDatePicker
                    v-model="form.end_date"
                    v-model:error="validationErrors.end_date"
                    label="Data Encerramento"
                    :rules="[optionalDateRule]"
                  />
                </div>

                <div class="col-5">
                  <DefaultSelect
                    v-model="form.package_id"
                    v-model:error="validationErrors.class_package_unit_id"
                    emit-value
                    label="Pacote de Aulas"
                    map-options
                    option-label="name"
                    option-value="id"
                    :options="packages"
                  />
                </div>

                <div class="col-7">
                  <DefaultInput
                    v-model="form.class_quantity"
                    v-model:error="validationErrors.class_quantity"
                    disable
                    label="Qtd. Aulas"
                    type="number"
                    :rules="[optionalIntegerRangeRule(1)]"
                  />
                </div>

                <div class="col-4">
                  <DefaultSelect
                    v-model="form.weekday"
                    v-model:error="validationErrors.weekday"
                    emit-value
                    label="Dia da Semana"
                    map-options
                    option-label="label"
                    option-value="value"
                    :options="weekdays"
                    :rules="[optionalIntegerRangeRule(0, 6)]"
                  />
                </div>

                <div class="col-4">
                  <DefaultInput
                    v-model="form.start_time"
                    v-model:error="validationErrors.start_time"
                    label="Hora de Início"
                    mask="##:##"
                    :rules="[optionalTimeRule]"
                  >
                    <template #append>
                      <q-icon name="mdi-clock-outline" />
                    </template>
                  </DefaultInput>
                </div>

                <div class="col-4">
                  <DefaultInput
                    v-model="form.end_time"
                    v-model:error="validationErrors.end_time"
                    label="Hora de Término"
                    mask="##:##"
                    :rules="[optionalTimeRule]"
                  >
                    <template #append>
                      <q-icon name="mdi-clock-outline" />
                    </template>
                  </DefaultInput>
                </div>

                <div class="col-4">
                  <DefaultSelect
                    v-model="form.second_weekday"
                    v-model:error="validationErrors.second_weekday"
                    emit-value
                    label="2° Dia da Semana"
                    map-options
                    option-label="label"
                    option-value="value"
                    :options="weekdays"
                    :rules="[optionalIntegerRangeRule(0, 6)]"
                  />
                </div>

                <div class="col-4">
                  <DefaultInput
                    v-model="form.second_start_time"
                    v-model:error="validationErrors.second_start_time"
                    label="Hora de Início"
                    mask="##:##"
                    :rules="[optionalTimeRule]"
                  >
                    <template #append>
                      <q-icon name="mdi-clock-outline" />
                    </template>
                  </DefaultInput>
                </div>

                <div class="col-4">
                  <DefaultInput
                    v-model="form.second_end_time"
                    v-model:error="validationErrors.second_end_time"
                    label="Hora de Término"
                    mask="##:##"
                    :rules="[optionalTimeRule]"
                  >
                    <template #append>
                      <q-icon name="mdi-clock-outline" />
                    </template>
                  </DefaultInput>
                </div>
              </div>

              <div class="text-subtitle1 q-mt-lg q-mb-md">
                Dados Financeiros
              </div>

              <div class="row q-col-gutter-sm">
                <div class="col-4">
                  <DefaultInput
                    v-model="form.due_day"
                    v-model:error="validationErrors.due_day"
                    label="Dia de Vencimento"
                    type="number"
                    :rules="[optionalIntegerRangeRule(1, 31)]"
                  />
                </div>
              </div>

              <div class="text-subtitle2 q-mt-md q-mb-sm text-grey-8">
                Matrícula
              </div>

              <div class="row q-col-gutter-sm">
                <div class="col-3">
                  <DefaultCurrencyInput
                    v-model="form.enrollment_fee"
                    v-model:error="validationErrors.tax_register"
                    disable
                    label="Valor da Matrícula"
                  />
                </div>

                <div class="col-3">
                  <DefaultSelect
                    v-model="form.installments"
                    v-model:error="validationErrors.installments"
                    emit-value
                    label="Qtde Parcelas"
                    map-options
                    option-label="label"
                    option-value="value"
                    :options="enrollmentInstallmentOptions"
                    :rules="[optionalIntegerRangeRule(1, 12)]"
                  />
                </div>

                <div class="col-3">
                  <DefaultCurrencyInput
                    v-model:error="validationErrors.installments"
                    :model-value="enrollmentInstallmentValue"
                    disable
                    label="Valor da Parcela"
                  />
                </div>

                <div class="col-3">
                  <DefaultInputDatePicker
                    v-model="form.enrollment_due_date"
                    v-model:error="validationErrors.enrollment_due_date"
                    label="Data Vencimento"
                    :rules="[optionalDateRule]"
                  />
                </div>
              </div>

              <div class="text-subtitle2 q-mt-md q-mb-sm text-grey-8">
                Pacote
              </div>

              <div class="row q-col-gutter-sm">
                <div class="col-3">
                  <DefaultCurrencyInput
                    v-model="form.package_value"
                    v-model:error="validationErrors.package_value"
                    disable
                    label="Valor do Pacote"
                  />
                </div>

                <div class="col-3">
                  <DefaultSelect
                    v-model="form.package_installments"
                    v-model:error="validationErrors.package_installments"
                    emit-value
                    label="Qtde Parcelas"
                    map-options
                    option-label="label"
                    option-value="value"
                    :options="packageInstallmentOptions"
                    :rules="[optionalIntegerRangeRule(1, 13)]"
                  />
                </div>

                <div class="col-3">
                  <DefaultCurrencyInput
                    v-model:error="validationErrors.package_installments"
                    :model-value="packageInstallmentValue"
                    disable
                    label="Valor da Parcela"
                  />
                </div>

                <div class="col-3">
                  <DefaultInputDatePicker
                    v-model="form.package_due_date"
                    v-model:error="validationErrors.package_due_date"
                    label="Data 1ª Parcela"
                    :rules="[optionalDateRule]"
                  />
                </div>
              </div>

              <div class="row q-col-gutter-sm q-mt-xs">
                <div class="col-6">
                  <DefaultInput
                    v-model="form.early_payment_discount"
                    v-model:error="validationErrors.early_payment_discount"
                    label="Desconto até o vencimento (%)"
                    type="number"
                    :rules="[optionalNumberRangeRule(0, 100)]"
                  />
                </div>

                <div class="col-6">
                  <DefaultSelect
                    v-model="form.payment_method"
                    v-model:error="validationErrors.payment_method"
                    emit-value
                    label="Forma de Pagamento"
                    map-options
                    option-label="label"
                    option-value="value"
                    :options="paymentMethods"
                    :rules="[
                      optionalOneOfRule([
                        'pix',
                        'credit_card',
                        'debit_card',
                      ]),
                    ]"
                  />
                </div>

                <div class="col-6">
                  <DefaultInput
                    v-model="form.interest_rate"
                    v-model:error="validationErrors.interest_rate"
                    label="Juros (%) a.m"
                    type="number"
                    :rules="[optionalNumberRangeRule(0)]"
                  />
                </div>

                <div class="col-6">
                  <DefaultInput
                    v-model="form.late_fee"
                    v-model:error="validationErrors.fine_cancelled"
                    label="Multa (%)"
                    type="number"
                    :rules="[optionalNumberRangeRule(0, 100)]"
                  />
                </div>
              </div>
            </div>

            <div
              v-if="props.contract"
              v-show="activeTab === 'midias'"
            >
              <DefaultTable
                v-model:rows="medias"
                :columns="mediaColumns"
                :feminino="true"
                :loading="loadingMedias"
                :show-search-field="false"
                descricao="mídias"
                no-api-call
                title="Mídias"
              >
                <template #body-cell-actions="{ row }">
                  <q-td align="center">
                    <q-item-section
                      class="no-wrap"
                      style="flex-direction: row; gap: 4px"
                    >
                      <q-btn
                        icon="mdi-eye-outline"
                        outline
                        style="width: 36px"
                        @click.prevent.stop="openFile(row.file_url)"
                      />

                      <q-btn
                        color="negative"
                        icon="mdi-trash-can-outline"
                        outline
                        style="width: 36px"
                        @click.prevent.stop="handleDeleteMedia(row)"
                      />
                    </q-item-section>
                  </q-td>
                </template>
              </DefaultTable>
            </div>
          </q-card-section>
        </q-scroll-area>

        <q-card-actions
          align="right"
          class="q-px-md q-pb-md"
        >
          <q-btn
            color="primary"
            label="Cancelar"
            no-caps
            outline
            @click="onDialogCancel"
          />

          <q-btn
            v-if="activeTab === 'dados'"
            color="primary"
            label="Salvar"
            no-caps
            type="submit"
            :loading="saving"
          />
        </q-card-actions>
      </DefaultForm>
    </q-card>
  </q-dialog>
</template>

<script setup>
import { addYears, format, isValid, parse } from "date-fns";

import {
  createStudentContract,
  updateStudentContract,
} from "src/api/studentContract";

import {
  computed,
  nextTick,
  onMounted,
  ref,
  useTemplateRef,
  watch,
} from "vue";

import {
  deleteContractMedia,
  getContractMedias,
} from "src/api/student_media";

import {
  formatDateDMYtoYMD,
  formatDateYMDtoDMY,
} from "src/helpers/utils";

import { getFinancialMe } from "src/api/unit_financial";
import { getStudentsForSelect } from "src/api/student";
import { getUnitMe } from "src/api/unit";
import { getUnitPackagesForSelect } from "src/api/package";
import { permissionStore } from "src/stores/permission";
import { useDialogPluginComponent, useQuasar } from "quasar";
import { useForm } from "src/composables/useForm";
import { useInputRules } from "src/composables/useInputRules";
import { useScroll } from "src/composables/useScroll";
import { useSubmitHandler } from "src/composables/useSubmitHandler";
import { userStore } from "src/stores/user";

import masks from "src/helpers/masks";

import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
import DefaultForm from "src/components/defaults/DefaultForm.vue";
import DefaultInput from "src/components/defaults/DefaultInput.vue";
import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
import DefaultTable from "src/components/defaults/DefaultTable.vue";
import AddEditStudentDialog from "src/pages/students/components/AddEditStudentDialog.vue";

defineEmits([...useDialogPluginComponent.emits]);

const props = defineProps({
  contract: {
    type: Object,
    default: null,
  },
  selectStudent: {
    type: Boolean,
    default: false,
  },
  student: {
    type: Object,
    default: null,
  },
});

const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
  useDialogPluginComponent();

const $q = useQuasar();
const { inputRules } = useInputRules();
const { scrollToComponent } = useScroll();

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

const formRef = useTemplateRef("formRef");
const scrollAreaRef = useTemplateRef("scrollAreaRef");

const activeTab = ref("dados");
const dateConfirmationOpen = ref(false);
const dateOverrideConfirmed = ref(false);
const filteredStudents = ref([]);
const loadingMedias = ref(false);
const medias = ref([]);
const packages = ref([]);
const restoringDefaultDates = ref(false);
const selectedStudent = ref(props.student);
const students = ref([]);
const syncingFromDate = ref(false);
const syncingFromDay = ref(false);
const unitDetails = ref(store.selectedUnit ?? {});

const canAddStudents = computed(() =>
  permissions.getAccess("franchisee_students", "add"),
);

const canViewFinancial = computed(() =>
  permissions.getAccess("franchisee_financial", "view"),
);

const currentStudent = computed(
  () => selectedStudent.value ?? props.student,
);

const dialogCardStyle = computed(() => ({
  height: props.selectStudent ? "95vh" : "auto",
  maxHeight: props.selectStudent ? "95vh" : "none",
  maxWidth: props.selectStudent ? "1400px" : "1350px",
  width: "100%",
}));

const enrollmentInstallmentValue = computed(() => {
  if (!form.enrollment_fee || !form.installments) {
    return null;
  }

  return Number(
    (form.enrollment_fee / form.installments).toFixed(2),
  );
});

const formattedBirthDate = computed(() =>
  currentStudent.value?.birth_date
    ? formatDateYMDtoDMY(currentStudent.value.birth_date)
    : "",
);

const packageInstallmentValue = computed(() => {
  if (!form.package_value || !form.package_installments) {
    return null;
  }

  return Number(
    (
      form.package_value /
      form.package_installments
    ).toFixed(2),
  );
});

const completeDatePattern = /^\d{2}\/\d{2}\/\d{4}$/;

const defaultContractDates = (() => {
  if (props.contract) return null;

  const startDate = new Date();

  return {
    end_date: format(addYears(startDate, 1), "dd/MM/yyyy"),
    signature_date: format(startDate, "dd/MM/yyyy"),
  };
})();

const enrollmentInstallmentOptions = Array.from(
  { length: 12 },
  (_, index) => ({
    label: `${index + 1}x`,
    value: index + 1,
  }),
);

const mediaColumns = [
  {
    align: "left",
    field: "created_at",
    label: "Data de Anexo",
    name: "created_at",
  },
  {
    align: "center",
    field: null,
    label: "Ações",
    name: "actions",
  },
];

const packageInstallmentOptions = Array.from(
  { length: 13 },
  (_, index) => ({
    label: `${index + 1}x`,
    value: index + 1,
  }),
);

const paymentMethods = [
  {
    label: "Pix",
    value: "pix",
  },
  {
    label: "Cartão de Crédito",
    value: "credit_card",
  },
  {
    label: "Cartão de Débito",
    value: "debit_card",
  },
];

const weekdays = [
  {
    label: "Segunda",
    value: 1,
  },
  {
    label: "Terça",
    value: 2,
  },
  {
    label: "Quarta",
    value: 3,
  },
  {
    label: "Quinta",
    value: 4,
  },
  {
    label: "Sexta",
    value: 5,
  },
  {
    label: "Sábado",
    value: 6,
  },
  {
    label: "Domingo",
    value: 0,
  },
];

const trimTime = (time) =>
  time ? time.slice(0, 5) : null;

const { form, getUpdatedFields } = useForm({
  class_quantity: props.contract?.class_quantity ?? null,
  due_day: props.contract?.recurring_day ?? null,

  early_payment_discount:
    props.contract?.early_payment_discount ?? null,

  end_date:
    props.contract?.end_date ??
    defaultContractDates?.end_date ??
    null,

  end_time: trimTime(props.contract?.end_time),

  enrollment_due_date:
    props.contract?.enrollment_due_date ?? null,

  enrollment_fee: props.contract?.tax_register ?? null,
  installments: props.contract?.installments ?? null,
  interest_rate: props.contract?.interest_rate ?? null,
  late_fee: props.contract?.fine_cancelled ?? null,
  package_due_date: props.contract?.package_due_date ?? null,

  package_id:
    props.contract?.class_package_unit_id ?? null,

  package_installments:
    props.contract?.package_installments ?? null,

  package_value: props.contract?.package_value ?? null,
  payment_method: props.contract?.payment_method ?? null,
  protocol: props.contract?.protocol ?? null,

  second_end_time: trimTime(
    props.contract?.second_end_time,
  ),

  second_start_time: trimTime(
    props.contract?.second_start_time,
  ),

  second_weekday:
    props.contract?.second_weekday ?? null,

  signature_date:
    props.contract?.signature_date ??
    defaultContractDates?.signature_date ??
    null,

  start_time: trimTime(props.contract?.start_time),
  total_classes: props.contract?.class_quantity ?? null,
  weekday: props.contract?.weekday ?? null,
});

const {
  loading: saving,
  validationErrors,
  execute,
} = useSubmitHandler({
  containerRef: scrollAreaRef,
  formRef,
  onSuccess: () => {
    onDialogOK(true);
  },
  scrollFn: scrollToComponent,
});

const buildDateFromDay = (day) => {
  const parsedDay = Number.parseInt(day);

  if (!parsedDay || parsedDay < 1 || parsedDay > 31) {
    return null;
  }

  const now = new Date();
  const nextMonthIndex = (now.getMonth() + 1) % 12;

  const nextYear =
    now.getMonth() === 11
      ? now.getFullYear() + 1
      : now.getFullYear();

  const lastDayOfNextMonth = new Date(
    nextYear,
    nextMonthIndex + 1,
    0,
  ).getDate();

  const safeDay = Math.min(
    parsedDay,
    lastDayOfNextMonth,
  );

  return `${String(safeDay).padStart(2, "0")}/${String(
    nextMonthIndex + 1,
  ).padStart(2, "0")}/${nextYear}`;
};

const buildPayload = () => ({
  class_package_unit_id: form.package_id,
  class_quantity: form.class_quantity,

  due_day: form.due_day
    ? Number.parseInt(form.due_day)
    : null,

  early_payment_discount: form.early_payment_discount,

  end_date: form.end_date
    ? formatDateDMYtoYMD(form.end_date)
    : null,

  end_time: form.end_time,

  enrollment_due_date: form.enrollment_due_date
    ? formatDateDMYtoYMD(form.enrollment_due_date)
    : null,

  fine_cancelled: form.late_fee,
  installments: form.installments,
  interest_rate: form.interest_rate,

  package_due_date: form.package_due_date
    ? formatDateDMYtoYMD(form.package_due_date)
    : null,

  package_installments: form.package_installments,
  package_value: form.package_value,
  payment_method: form.payment_method,
  protocol: form.protocol,
  second_end_time: form.second_end_time,
  second_start_time: form.second_start_time,
  second_weekday: form.second_weekday,

  signature_date: form.signature_date
    ? formatDateDMYtoYMD(form.signature_date)
    : null,

  start_time: form.start_time,
  student_id: currentStudent.value?.id ?? null,
  tax_register: form.enrollment_fee,
  weekday: form.weekday,
});

const calculateEndTime = (
  startTime,
  durationMinutes = 120,
) => {
  if (!/^\d{2}:\d{2}$/.test(startTime ?? "")) {
    return null;
  }

  const [hours, minutes] = startTime
    .split(":")
    .map(Number);

  if (hours > 23 || minutes > 59) {
    return null;
  }

  const endMinutes =
    (hours * 60 + minutes + durationMinutes) %
    (24 * 60);

  return `${String(
    Math.floor(endMinutes / 60),
  ).padStart(2, "0")}:${String(
    endMinutes % 60,
  ).padStart(2, "0")}`;
};

const emptyOptionalValue = (value) =>
  value == null || value === "";

const fetchMedias = async () => {
  if (!props.contract) return;

  loadingMedias.value = true;

  try {
    medias.value = await getContractMedias(
      props.contract.id,
    );
  } finally {
    loadingMedias.value = false;
  }
};

const filterStudents = (value, update) => {
  update(() => {
    const search = value
      .trim()
      .toLocaleLowerCase("pt-BR");

    filteredStudents.value = search
      ? students.value.filter((student) =>
          student.name
            .toLocaleLowerCase("pt-BR")
            .includes(search),
        )
      : students.value;
  });
};

const handleDeleteMedia = (media) => {
  $q.dialog({
    cancel: {
      color: "primary",
      label: "Cancelar",
      outline: true,
    },
    message: "Deseja excluir esta mídia permanentemente?",
    ok: {
      color: "negative",
      label: "Excluir",
    },
    title: "Excluir mídia",
  }).onOk(async () => {
    try {
      await deleteContractMedia(media.id);

      medias.value = medias.value.filter(
        (item) => item.id !== media.id,
      );
    } catch (error) {
      console.error(error);

      $q.notify({
        message: "Erro ao excluir mídia.",
        type: "negative",
      });
    }
  });
};

const handleSave = async () => {
  const payload = buildPayload();

  await execute(() => {
    if (!props.contract) {
      return createStudentContract(payload);
    }

    const changedFields = getUpdatedFields.value;

    const updatePayload = {
      student_id: currentStudent.value?.id ?? null,
    };

    const fieldMap = {
      enrollment_fee: "tax_register",
      late_fee: "fine_cancelled",
      package_id: "class_package_unit_id",
      total_classes: "class_quantity",
    };

    for (const key of [
      "protocol",
      "class_quantity",
      "weekday",
      "start_time",
      "end_time",
      "second_weekday",
      "second_start_time",
      "second_end_time",
      "installments",
      "package_value",
      "package_installments",
      "early_payment_discount",
      "interest_rate",
      "payment_method",
    ]) {
      if (key in changedFields) {
        updatePayload[key] = payload[key];
      }
    }

    for (const [source, target] of Object.entries(
      fieldMap,
    )) {
      if (source in changedFields) {
        updatePayload[target] = payload[target];
      }
    }

    for (const key of [
      "signature_date",
      "end_date",
      "enrollment_due_date",
      "package_due_date",
    ]) {
      if (key in changedFields) {
        updatePayload[key] = payload[key];
      }
    }

    if ("due_day" in changedFields) {
      updatePayload.due_day = payload.due_day;
    }

    return updateStudentContract(
      props.contract.id,
      updatePayload,
    );
  });
};

const openCreateStudent = () => {
  $q.dialog({
    component: AddEditStudentDialog,
  }).onOk(async (createdStudent) => {
    const unitStudents = await getStudentsForSelect();

    students.value = unitStudents;
    filteredStudents.value = unitStudents;

    selectedStudent.value =
      unitStudents.find(
        (student) => student.id === createdStudent?.id,
      ) ?? createdStudent;
  });
};

const openFile = (url) => {
  window.open(url, "_blank");
};

const optionalDateRule = (value) => {
  if (emptyOptionalValue(value)) return true;

  const parsedDate = parse(
    value,
    "dd/MM/yyyy",
    new Date(),
  );

  return (
    (isValid(parsedDate) &&
      format(parsedDate, "dd/MM/yyyy") === value) ||
    "Informe uma data válida."
  );
};

const optionalIntegerRangeRule =
  (min, max = null) =>
  (value) => {
    if (emptyOptionalValue(value)) return true;

    const number = Number(value);

    const withinRange =
      number >= min &&
      (max == null || number <= max);

    if (Number.isInteger(number) && withinRange) {
      return true;
    }

    return max == null
      ? `Informe um número inteiro maior ou igual a ${min}.`
      : `Informe um número inteiro entre ${min} e ${max}.`;
  };

const optionalMaxLengthRule = (max) => (value) =>
  emptyOptionalValue(value) ||
  String(value).length <= max ||
  `Informe no máximo ${max} caracteres.`;

const optionalNumberRangeRule =
  (min, max = null) =>
  (value) => {
    if (emptyOptionalValue(value)) return true;

    const number = Number(value);

    const withinRange =
      number >= min &&
      (max == null || number <= max);

    if (Number.isFinite(number) && withinRange) {
      return true;
    }

    return max == null
      ? `Informe um valor maior ou igual a ${min}.`
      : `Informe um valor entre ${min} e ${max}.`;
  };

const optionalOneOfRule = (allowedValues) => (value) =>
  emptyOptionalValue(value) ||
  allowedValues.includes(value) ||
  "Selecione uma opção válida.";

const optionalTimeRule = (value) => {
  if (emptyOptionalValue(value)) return true;

  const match = /^(\d{2}):(\d{2})$/.exec(value);

  return (
    (!!match &&
      Number(match[1]) <= 23 &&
      Number(match[2]) <= 59) ||
    "Informe um horário válido."
  );
};

const restoreDefaultContractDates = () => {
  restoringDefaultDates.value = true;

  form.signature_date = defaultContractDates.signature_date;

  form.end_date = defaultContractDates.end_date;

  nextTick(() => {
    dateConfirmationOpen.value = false;
    restoringDefaultDates.value = false;
  });
};

watch(
  [() => form.signature_date, () => form.end_date],
  ([signatureDate, endDate]) => {
    if (
      props.contract ||
      dateOverrideConfirmed.value ||
      dateConfirmationOpen.value ||
      restoringDefaultDates.value
    ) {
      return;
    }

    const datesAreStillDefault =
      signatureDate ===
        defaultContractDates.signature_date &&
      endDate === defaultContractDates.end_date;

    if (datesAreStillDefault) return;

    const datesAreComplete =
      (!signatureDate ||
        completeDatePattern.test(signatureDate)) &&
      (!endDate ||
        completeDatePattern.test(endDate));

    if (!datesAreComplete) return;

    dateConfirmationOpen.value = true;

    $q.dialog({
      cancel: {
        color: "primary",
        label: "Não",
        outline: true,
      },
      message:
        "As datas foram preenchidas automaticamente para a duração de um ano. Tem certeza de que deseja alterá-las?",
      ok: {
        color: "primary",
        label: "Sim",
      },
      persistent: true,
      title: "Alterar duração do contrato?",
    })
      .onOk(() => {
        dateConfirmationOpen.value = false;
        dateOverrideConfirmed.value = true;
      })
      .onCancel(restoreDefaultContractDates);
  },
);

watch(
  () => form.due_day,
  (day) => {
    if (syncingFromDate.value) return;

    const dateString = buildDateFromDay(day);

    if (!dateString) return;

    syncingFromDay.value = true;
    form.package_due_date = dateString;

    nextTick(() => {
      syncingFromDay.value = false;
    });
  },
);

watch(
  () => form.package_due_date,
  (dateString) => {
    if (syncingFromDay.value) return;

    if (!dateString || dateString.length < 8) return;

    const day = Number.parseInt(
      dateString.split("/")[0],
    );

    if (
      !Number.isNaN(day) &&
      day !== Number.parseInt(form.due_day)
    ) {
      syncingFromDate.value = true;
      form.due_day = day;

      nextTick(() => {
        syncingFromDate.value = false;
      });
    }
  },
);

watch(activeTab, (tab) => {
  if (tab === "midias") {
    fetchMedias();
  }
});

watch(
  () => form.package_id,
  (id) => {
    const selectedPackage = packages.value.find(
      (item) => item.id === id,
    );

    if (!selectedPackage) return;

    form.class_quantity =
      selectedPackage.quantity_classes;

    form.total_classes =
      selectedPackage.quantity_classes;

    form.enrollment_fee =
      selectedPackage.contract_register_value;

    form.package_value =
      selectedPackage.contract_value;

    form.weekday = selectedPackage.weekday ?? null;

    form.start_time = trimTime(
      selectedPackage.start_time,
    );

    form.end_time = calculateEndTime(
      form.start_time,
      selectedPackage.class_duration_minutes ?? 120,
    );

    form.second_weekday =
      selectedPackage.second_weekday ?? null;

    form.second_start_time = trimTime(
      selectedPackage.second_start_time,
    );

    form.second_end_time = calculateEndTime(
      form.second_start_time,
      selectedPackage.class_duration_minutes ?? 120,
    );
  },
);

watch(
  () => form.start_time,
  (startTime) => {
    const selectedPackage = packages.value.find(
      (item) => item.id === form.package_id,
    );

    const calculatedEndTime = calculateEndTime(
      startTime,
      selectedPackage?.class_duration_minutes ?? 120,
    );

    if (calculatedEndTime) {
      form.end_time = calculatedEndTime;
    }
  },
);

watch(
  () => form.second_start_time,
  (startTime) => {
    const selectedPackage = packages.value.find(
      (item) => item.id === form.package_id,
    );

    const calculatedEndTime = calculateEndTime(
      startTime,
      selectedPackage?.class_duration_minutes ?? 120,
    );

    if (calculatedEndTime) {
      form.second_end_time = calculatedEndTime;
    }
  },
);

onMounted(async () => {
  const unitRequest = getUnitMe().catch((error) => {
    console.error(
      "Falha ao carregar os dados da unidade:",
      error,
    );

    return store.selectedUnit;
  });

  const requests = [
    getUnitPackagesForSelect(),
    unitRequest,
  ];

  if (props.selectStudent) {
    requests.push(getStudentsForSelect());
  }

  const [
    unitPackages,
    unitData,
    unitStudents = [],
  ] = await Promise.all(requests);

  packages.value = unitPackages;

  unitDetails.value =
    unitData ?? store.selectedUnit ?? {};

  students.value = unitStudents;
  filteredStudents.value = unitStudents;

  if (!props.contract && canViewFinancial.value) {
    try {
      const financial = await getFinancialMe();

      if (!financial) return;

      if (financial.default_discount != null) {
        form.early_payment_discount =
          financial.default_discount;
      }

      if (financial.default_interest != null) {
        form.interest_rate =
          financial.default_interest;
      }

      if (financial.default_fine != null) {
        form.late_fee = financial.default_fine;
      }
    } catch (error) {
      console.error(error);
    }
  }
});
</script>
