<template>
  <div>
    <DefaultHeaderPage
      :show-filter-icon="false"
      title="Contas a Receber"
    />

    <div class="row q-pa-md q-gutter-md">
      <FinancialCard
        :financial-value="totals.received"
        :integer="totals.receivedCount"
        icon="mdi-check-circle-outline"
        integer-label="recebimentos"
        title="Recebido"
      />

      <FinancialCard
        :financial-value="totals.pending"
        :integer="totals.pendingCount"
        icon="mdi-cash-plus"
        integer-label="pendentes"
        title="A Receber"
      />

      <FinancialCard
        :financial-value="totals.overdue"
        :integer="totals.overdueCount"
        icon="mdi-alert-circle-outline"
        integer-label="em atraso"
        title="Vencidas"
      />
    </div>

    <div class="q-px-md">
      <DefaultTable
        v-model:rows="rows"
        :add-item="canAdd"
        :columns="columns"
        :female="true"
        description="contas"
        no-api-call
        title="Contas a Receber"
        @on-add-item="openCreate"
      >
        <template #body-cell-value="{ row }">
          <q-td class="text-left">
            {{ formatCurrency(row.value) }}
          </q-td>
        </template>

        <template #body-cell-status="{ row }">
          <q-td class="text-left">
            <q-btn
              :color="row.status === 'paid' ? 'positive' : 'secondary'"
              :disable="!canEdit || row.status === 'paid'"
              :label="row.status === 'paid' ? 'Pago' : 'Não pago'"
              dense
              no-caps
              unelevated
              @click.stop="changeStatus(row)"
            >
              <q-tooltip v-if="canEdit && row.status !== 'paid'">
                Dar baixa
              </q-tooltip>
            </q-btn>
          </q-td>
        </template>

        <template #body-cell-actions="{ row }">
          <q-td auto-width>
            <div
              class="row no-wrap justify-end items-center"
              style="gap: 6px"
            >
              <q-btn
                v-if="row.invoice_url"
                class="q-px-sm"
                color="teal-7"
                dense
                icon="mdi-barcode"
                label="Ver boleto"
                no-caps
                outline
                @click="openInvoice(row)"
              />

              <q-btn
                v-else-if="
                  canEdit &&
                  row.source !== 'manual' &&
                  row.status !== 'paid' &&
                  row.status !== 'cancelled'
                "
                aria-label="Gerar cobrança"
                color="deep-purple-5"
                dense
                icon="mdi-cash-fast"
                outline
                round
                :loading="chargingId === row.id"
                @click="onCharge(row)"
              >
                <q-tooltip>
                  Gerar cobrança no Asaas
                </q-tooltip>
              </q-btn>
            </div>
          </q-td>
        </template>
      </DefaultTable>
    </div>

    <q-dialog v-model="createDialog">
      <q-card
        class="dialog-form-card"
        style="min-width: 380px; max-width: 480px"
      >
        <DefaultDialogHeader
          title="Nova conta a receber"
          @close="createDialog = false"
        />

        <DefaultForm
          ref="createFormRef"
          @submit="onCreate"
        >
          <q-scroll-area
            ref="createScrollAreaRef"
            class="dialog-form-scroll dialog-form-scroll--md"
          >
            <q-card-section class="q-gutter-sm">
              <DefaultInput
                v-model="createForm.history"
                v-model:error="createValidationErrors.history"
                label="Descrição"
                outlined
                :rules="[inputRules.required]"
              />

              <div
                style="
                  display: grid;
                  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
                  gap: 8px;
                "
              >
                <DefaultCurrencyInput
                  v-model="createForm.value"
                  v-model:error="createValidationErrors.value"
                  label="Valor"
                  outlined
                  :rules="[inputRules.required, positiveAmountRule]"
                />

                <DefaultInputDatePicker
                  v-model="createForm.due_date"
                  v-model:error="createValidationErrors.due_date"
                  v-model:untreated-date="createForm.due_date_iso"
                  label="Vencimento"
                  :rules="[inputRules.required]"
                />
              </div>

              <DefaultSelect
                v-if="canViewStudents"
                v-model="createForm.student_id"
                clearable
                emit-value
                label="Aluno (opcional)"
                map-options
                outlined
                :loading="loadingAux"
                :options="studentOptions"
              />

              <DefaultSelect
                v-model="createForm.financial_plan_account_id"
                clearable
                emit-value
                label="Plano de contas (opcional)"
                map-options
                outlined
                :loading="loadingAux"
                :options="planAccountOptions"
              />

              <DefaultInput
                v-model="createForm.obs"
                autogrow
                label="Observação (opcional)"
                outlined
                type="textarea"
              />
            </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="createDialog = false"
            />

            <q-btn
              color="primary"
              label="Salvar"
              no-caps
              type="submit"
              :loading="creating"
            />
          </q-card-actions>
        </DefaultForm>
      </q-card>
    </q-dialog>

    <q-dialog v-model="settleDialog">
      <q-card
        class="dialog-form-card"
        style="min-width: 360px; max-width: 460px"
      >
        <DefaultDialogHeader
          title="Dar baixa"
          @close="settleDialog = false"
        />

        <DefaultForm @submit="onSettle">
          <q-scroll-area class="dialog-form-scroll dialog-form-scroll--sm">
            <q-card-section class="q-gutter-sm">
              <div class="text-body2 text-grey-8">
                {{ selected?.student_name }} — {{ selected?.history }}
                ({{ selected?.order }})
              </div>

              <DefaultInputDatePicker
                v-model="settleForm.payment_date"
                v-model:untreated-date="settleForm.payment_date_iso"
                label="Data do pagamento"
              />

              <div class="row q-col-gutter-sm">
                <DefaultCurrencyInput
                  v-model="settleForm.discount"
                  class="col-6"
                  label="Desconto"
                  outlined
                />

                <DefaultCurrencyInput
                  v-model="settleForm.fine"
                  class="col-6"
                  label="Multa/Juros"
                  outlined
                />
              </div>

              <div class="text-caption text-grey-7">
                Valor da parcela: {{ formatCurrency(selected?.value) }} ·

                <span class="text-weight-medium">
                  Recebido: {{ formatCurrency(settleNetValue) }}
                </span>
              </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="settleDialog = false"
            />

            <q-btn
              color="primary"
              label="Confirmar baixa"
              no-caps
              type="submit"
              :loading="settling"
            />
          </q-card-actions>
        </DefaultForm>
      </q-card>
    </q-dialog>
  </div>
</template>

<script setup>
import {
  chargeReceivableMe,
  createManualReceivableMe,
  getReceivablesMe,
  settleManualReceivableMe,
  settleReceivableMe,
} from "src/api/unit_receivable";

import { computed, onMounted, ref, useTemplateRef } from "vue";
import { getPlanAccountsForSelect } from "src/api/financial_plan_account";
import { getStudentsForSelect } from "src/api/student";
import { permissionStore } from "src/stores/permission";
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 DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
import DefaultForm from "src/components/defaults/DefaultForm.vue";
import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.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 FinancialCard from "src/components/financial/FinancialCard.vue";

const { inputRules } = useInputRules();
const { scrollToComponent } = useScroll();

const permissions = permissionStore();

const createFormRef = useTemplateRef("createFormRef");
const createScrollAreaRef = useTemplateRef("createScrollAreaRef");

const chargingId = ref(null);
const createDialog = ref(false);
const loadingAux = ref(false);
const planAccountOptions = ref([]);
const rows = ref([]);
const selected = ref(null);
const settleDialog = ref(false);

const settleForm = ref({
  discount: 0,
  fine: 0,
  payment_date: null,
  payment_date_iso: null,
});

const settling = ref(false);
const studentOptions = ref([]);

const canAdd = computed(() =>
  permissions.getAccess("franchisee_financial", "add"),
);

const canEdit = computed(() =>
  permissions.getAccess("franchisee_financial", "edit"),
);

const settleNetValue = computed(() => {
  const baseValue = Number(selected.value?.value ?? 0);
  const discount = Number(settleForm.value.discount ?? 0);
  const fine = Number(settleForm.value.fine ?? 0);

  return baseValue - discount + fine;
});

const totals = computed(() => {
  const accumulatedTotals = {
    overdue: 0,
    overdueCount: 0,
    pending: 0,
    pendingCount: 0,
    received: 0,
    receivedCount: 0,
  };

  for (const row of rows.value) {
    if (row.status === "paid") {
      accumulatedTotals.received += Number(row.paid_value ?? 0);
      accumulatedTotals.receivedCount += 1;

      continue;
    }

    if (row.status === "overdue") {
      accumulatedTotals.overdue += Number(row.value ?? 0);
      accumulatedTotals.overdueCount += 1;

      continue;
    }

    if (row.status === "pending") {
      accumulatedTotals.pending += Number(row.value ?? 0);
      accumulatedTotals.pendingCount += 1;
    }
  }

  return accumulatedTotals;
});

const columns = [
  {
    align: "left",
    field: "student_name",
    label: "Aluno",
    name: "student_name",
  },
  {
    align: "left",
    field: "history",
    label: "Descrição",
    name: "history",
  },
  {
    align: "left",
    field: "order",
    label: "Parcela",
    name: "order",
  },
  {
    align: "left",
    field: "value",
    label: "Valor",
    name: "value",
  },
  {
    align: "left",
    field: "due_date",
    label: "Vencimento",
    name: "due_date",
  },
  {
    align: "left",
    field: "status",
    label: "Status",
    name: "status",
  },
  {
    align: "right",
    field: "actions",
    label: "Ações",
    name: "actions",
  },
];

const defaultCreateForm = () => {
  const today = new Date();

  return {
    due_date: today.toLocaleDateString("pt-BR"),
    due_date_iso: today.toISOString().slice(0, 10),
    financial_plan_account_id: null,
    history: "",
    obs: "",
    student_id: null,
    value: 0,
  };
};

const { form: createForm } = useForm(defaultCreateForm());

const {
  loading: creating,
  validationErrors: createValidationErrors,
  execute: executeCreate,
} = useSubmitHandler({
  containerRef: createScrollAreaRef,
  formRef: createFormRef,
  onSuccess: async () => {
    createDialog.value = false;

    await loadData();
  },
  scrollFn: scrollToComponent,
});

const changeStatus = (row) => {
  if (row.status === "paid") return;

  openSettle(row);
};

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

const loadAux = async () => {
  if (
    studentOptions.value.length ||
    planAccountOptions.value.length
  ) {
    return;
  }

  loadingAux.value = true;

  try {
    const [students, planAccounts] = await Promise.all([
      getStudentsForSelect(),
      getPlanAccountsForSelect(),
    ]);

    studentOptions.value = (students ?? []).map((student) => ({
      label: student.name,
      value: student.id,
    }));

    planAccountOptions.value = (planAccounts ?? []).map((account) => ({
      label: `${account.code} — ${account.description}`,
      value: account.id,
    }));
  } catch (error) {
    console.error("Erro ao carregar dados auxiliares:", error);
  } finally {
    loadingAux.value = false;
  }
};

const loadData = async () => {
  try {
    const data = await getReceivablesMe();

    // chave composta: parcelas e avulsos podem ter o mesmo id numerico.
    // realId e o id verdadeiro usado nas acoes (baixa/reabrir/cobranca).

    rows.value = (data ?? []).map((row) => ({
      ...row,
      id: `${row.source}-${row.id}`,
      realId: row.id,
    }));
  } catch (error) {
    console.error("Erro ao buscar contas a receber:", error);
  }
};

const onCharge = async (row) => {
  chargingId.value = row.id;

  try {
    await chargeReceivableMe(row.realId);

    await loadData();
  } catch (error) {
    console.error(error);
  } finally {
    chargingId.value = null;
  }
};

const onCreate = async () => {
  await executeCreate(() =>
    createManualReceivableMe({
      due_date: createForm.due_date_iso,

      financial_plan_account_id:
        createForm.financial_plan_account_id || null,

      history: createForm.history,
      obs: createForm.obs || null,
      student_id: createForm.student_id || null,
      value: createForm.value,
    }),
  );
};

const onSettle = async () => {
  if (!selected.value) return;

  const payload = {
    discount: settleForm.value.discount,
    fine: settleForm.value.fine,
    payment_date: settleForm.value.payment_date_iso,
  };

  settling.value = true;

  try {
    if (selected.value.source === "manual") {
      await settleManualReceivableMe(
        selected.value.realId,
        payload,
      );
    } else {
      await settleReceivableMe(
        selected.value.realId,
        payload,
      );
    }

    settleDialog.value = false;

    await loadData();
  } catch (error) {
    console.error(error);
  } finally {
    settling.value = false;
  }
};

const openCreate = () => {
  Object.assign(createForm, defaultCreateForm());

  createDialog.value = true;

  loadAux();
};

const openInvoice = (row) => {
  if (!row.invoice_url) return;

  window.open(row.invoice_url, "_blank");
};

const openSettle = (row) => {
  const today = new Date();

  selected.value = row;

  settleForm.value = {
    discount: Number(row.discount ?? 0),
    fine: Number(row.fine ?? 0),
    payment_date: today.toLocaleDateString("pt-BR"),
    payment_date_iso: today.toISOString().slice(0, 10),
  };

  settleDialog.value = true;
};

const positiveAmountRule = (value) =>
  Number(value) > 0 || "Informe um valor maior que zero.";

onMounted(loadData);
</script>