<template>
  <q-dialog ref="dialogRef" @hide="onDialogHide">
    <q-card
      class="q-dialog-plugin dialog-form-card"
      style="width: 100%; max-width: 860px"
    >
      <DefaultDialogHeader
        title="Trancar Contrato"
        @close="onDialogCancel"
      />

      <q-scroll-area class="dialog-form-scroll">
        <q-card-section class="q-pt-sm">
          <div class="row q-col-gutter-sm q-mb-md items-center">
            <div class="col-12 col-md-4">
              <DefaultSelect
                v-model="selectedMonths"
                emit-value
                label="Tempo de Trancamento"
                map-options
                option-label="label"
                option-value="value"
                :option-disable="(option) => option.disable"
                :options="monthOptions"
              />
            </div>

            <div
              v-if="selectedMonths"
              class="col-12 col-md-8"
            >
              <q-banner
                class="bg-blue-1 text-blue-9"
                dense
                rounded
              >
                <template #avatar>
                  <q-icon
                    color="blue-7"
                    name="mdi-information-outline"
                  />
                </template>

                {{ pendingInstallments.length }} parcela(s) pendente(s) serão
                adiadas

                <strong>
                  {{ selectedMonths }}
                  {{ selectedMonths === 1 ? "mês" : "meses" }}
                </strong>.
              </q-banner>
            </div>
          </div>

          <div
            v-if="loading"
            class="flex flex-center q-py-lg"
          >
            <q-spinner
              color="primary"
              size="32px"
            />
          </div>

          <div
            v-else-if="!pendingInstallments.length"
            class="text-center text-grey-6 q-py-lg"
          >
            Nenhuma parcela pendente encontrada para este contrato.
          </div>

          <q-table
            v-else
            bordered
            class="q-mt-sm"
            dense
            flat
            hide-pagination
            :columns="tableColumns"
            :rows="previewRows"
            :rows-per-page-options="[0]"
          >
            <template #body-cell-new_due_date="{ row }">
              <q-td align="center">
                <span
                  v-if="row.new_due_date"
                  class="text-positive text-weight-medium"
                >
                  {{ row.new_due_date }}
                </span>

                <span
                  v-else
                  class="text-grey-5"
                >
                  —
                </span>
              </q-td>
            </template>

            <template #body-cell-value="{ row }">
              <q-td align="right">
                {{ formatCurrency(row.value) }}
              </q-td>
            </template>
          </q-table>
        </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
          color="primary"
          label="Confirmar trancamento"
          no-caps
          :disable="
            !selectedMonths ||
            !pendingInstallments.length
          "
          :loading="saving"
          @click="handleConfirm"
        />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

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

import {
  freezeContract,
  getContractInstallments,
} from "src/api/studentContract";

import { getFinancialMe } from "src/api/unit_financial";
import { permissionStore } from "src/stores/permission";
import { useDialogPluginComponent, useQuasar } from "quasar";

import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
import DefaultSelect from "src/components/defaults/DefaultSelect.vue";

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

const props = defineProps({
  contract: {
    type: Object,
    required: true,
  },
});

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

const $q = useQuasar();

const permissions = permissionStore();

const loading = ref(true);
const maxFreezeCount = ref(null);
const pendingInstallments = ref([]);
const saving = ref(false);
const selectedMonths = ref(null);

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

const monthOptions = computed(() => {
  const maxFreezeMonths = maxFreezeCount.value;
  const limit = maxFreezeMonths ?? 12;

  const options = Array.from(
    { length: limit },
    (_, index) => {
      const months = index + 1;

      return {
        disable: false,
        label:
          months === 1
            ? "1 mês"
            : `${months} meses`,
        value: months,
      };
    },
  );

  if (maxFreezeMonths) {
    options.push({
      disable: true,
      label:
        `Acima de ${maxFreezeMonths} meses — ` +
        "não permitido",
      value: null,
    });
  }

  return options;
});

const previewRows = computed(() =>
  pendingInstallments.value.map((installment) => ({
    ...installment,
    new_due_date: selectedMonths.value
      ? addMonthsToDMY(
          installment.due_date,
          selectedMonths.value,
        )
      : null,
  })),
);

const tableColumns = [
  {
    align: "left",
    field: "history",
    label: "Histórico",
    name: "history",
  },
  {
    align: "center",
    field: "order",
    label: "Ordem",
    name: "order",
  },
  {
    align: "right",
    field: "value",
    label: "Valor",
    name: "value",
  },
  {
    align: "center",
    field: "due_date",
    label: "Vencimento Atual",
    name: "due_date",
  },
  {
    align: "center",
    field: "new_due_date",
    label: "Novo Vencimento",
    name: "new_due_date",
  },
];

const addMonthsToDMY = (dateString, months) => {
  if (!dateString) return null;

  const [day, month, year] = dateString
    .split("/")
    .map(Number);

  const targetMonthStart = new Date(
    year,
    month - 1 + months,
    1,
  );

  const lastDay = new Date(
    targetMonthStart.getFullYear(),
    targetMonthStart.getMonth() + 1,
    0,
  ).getDate();

  const safeDay = Math.min(day, lastDay);

  return `${String(safeDay).padStart(2, "0")}/${String(
    targetMonthStart.getMonth() + 1,
  ).padStart(2, "0")}/${targetMonthStart.getFullYear()}`;
};

const formatCurrency = (value) =>
  new Intl.NumberFormat("pt-BR", {
    currency: "BRL",
    style: "currency",
  }).format(value ?? 0);

const handleConfirm = async () => {
  if (!selectedMonths.value) return;

  saving.value = true;

  try {
    const updatedContract = await freezeContract(
      props.contract.id,
      selectedMonths.value,
    );

    $q.notify({
      message: "Contrato trancado com sucesso!",
      type: "positive",
    });

    onDialogOK(updatedContract);
  } catch (error) {
    const message =
      error?.response?.data?.message ??
      "Erro ao trancar contrato.";

    $q.notify({
      message,
      type: "negative",
    });
  } finally {
    saving.value = false;
  }
};

onMounted(async () => {
  try {
    const [installments, financial] = await Promise.all([
      getContractInstallments(props.contract.id),
      canViewFinancial.value
        ? getFinancialMe()
        : Promise.resolve(null),
    ]);

    pendingInstallments.value = installments ?? [];

    maxFreezeCount.value =
      financial?.max_freeze_count ?? null;
  } catch (error) {
    console.error(error);

    $q.notify({
      message: "Erro ao carregar parcelas.",
      type: "negative",
    });
  } finally {
    loading.value = false;
  }
});
</script>
