<template>
  <div>
    <DefaultHeaderPage title="Tesouraria" :show-filter-icon="false" />

    <div class="flex justify-end">
      <q-btn v-if="!loading && canAdd" color="primary" style="height: 40px; width: 40px;" icon="mdi-plus" @click="openCreateDialog"/>
    </div>
    <div class="row q-pa-md q-col-gutter-md items-stretch">
      <div v-for="bank in cards" :key="bank.key" class="col-3">
        <FinancialCard
          :title="bank.label"
          :icon="bank.icon"
          :financial-value="bank.value"
          :percentage="bank.percentage"
          clickable
          :editable="canEdit && !!bank.account"
          :selected="selectedBank.key === bank.key"
          @click="selectedBank = bank"
          @edit="openEditDialog(bank.account)"
        />
      </div>
    </div>

    <div class="q-px-md">
      <DefaultTable
        v-model:rows="rows"
        no-api-call
        :add-item="canAdd"
        :title="`Extrato ${selectedBank.label}`"
        description="registros"
        :female="false"
        :columns="columns"
        @on-add-item="handleAddItem"
      >
        <template #body-cell-actions="{ row }">
          <q-td>
            <div class="row no-wrap q-gutter-xs">
              <q-btn
                v-if="canEdit"
                outline
                icon="mdi-pencil-outline"
                style="width: 36px"
                aria-label="Editar movimentação"
                @click.prevent.stop="handleEditLaunch(row)"
              >
                <q-tooltip>Editar</q-tooltip>
              </q-btn>
              <q-btn
                v-if="canDelete"
                outline
                color="negative"
                icon="mdi-trash-can-outline"
                style="width: 36px"
                aria-label="Excluir movimentação"
                :loading="deletingId === row.id"
                @click.prevent.stop="handleDeleteLaunch(row)"
              >
                <q-tooltip>Excluir</q-tooltip>
              </q-btn>
            </div>
          </q-td>
        </template>
      </DefaultTable>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch } from "vue";
import { useQuasar } from "quasar";
import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
import DefaultTable from "src/components/defaults/DefaultTable.vue";
import FinancialCard from "src/components/financial/FinancialCard.vue";
import AddEditTreasuryAccountDialog from "src/components/financial/AddEditTreasuryAccountDialog.vue";
import AddTreasuryLaunchDialog from "src/components/financial/AddTreasuryLaunchDialog.vue";
import { getTreasuryAccounts } from "src/api/treasury_account";
import { getTreasuryLaunches, deleteTreasuryLaunch } from "src/api/treasury_launch";
import { formatToBRLCurrency, formatDateYMDtoDMY } from "src/helpers/utils";
import { permissionStore } from "src/stores/permission";

const $q = useQuasar();
const permissions = permissionStore();
const canAdd = permissions.getAccess("franchisor_financial", "add");
const canEdit = permissions.getAccess("franchisor_financial", "edit");
const canDelete = permissions.getAccess("franchisor_financial", "delete");

const accounts = ref([]);
const launches = ref([]);
const loading = ref(false);
const deletingId = ref(null);

// Variação % do saldo vs. o fim do mês anterior.
const monthPercentage = (current, previous) => {
  if (previous === 0) return current > 0 ? 100 : 0;
  return Math.round(((current - previous) / Math.abs(previous)) * 1000) / 10;
};

const totalCard = computed(() => {
  const value = accounts.value.reduce((sum, account) => sum + (account.balance ?? 0), 0);
  const previous = accounts.value.reduce((sum, account) => sum + (account.balance_previous ?? 0), 0);
  return {
    key: "total",
    label: "Saldo Total",
    icon: "mdi-bank",
    value,
    percentage: monthPercentage(value, previous),
  };
});

const selectedBank = ref({ key: "total", label: "Saldo Total" });

const cards = computed(() => [
  totalCard.value,
  ...accounts.value.map((account) => ({
    key: `account-${account.id}`,
    label: account.name,
    icon: "mdi-bank-outline",
    value: account.balance ?? 0,
    percentage: monthPercentage(account.balance ?? 0, account.balance_previous ?? 0),
    account,
  })),
]);

const rows = computed(() =>
  launches.value.map((launch) => {
    const isIncome = launch.transaction_type === "entrada";
    return {
      ...launch,
      plan_account: launch.financial_plan_account?.label ?? "—",
      value: `${isIncome ? "+ " : "- "}${formatToBRLCurrency(launch.amount)}`,
      updated_at: formatDateYMDtoDMY(launch.updated_at),
    };
  }),
);

const columns = [
  { name: "description", label: "Descrição", field: "description", align: "left" },
  { name: "plan_account", label: "Plano de Contas", field: "plan_account", align: "left" },
  { name: "value", label: "Valor", field: "value", align: "left" },
  { name: "updated_at", label: "Atualização", field: "updated_at", align: "left" },
  { name: "actions", label: "Ações", field: null, align: "center" },
];

const fetchAccounts = async () => {
  loading.value = true;
  try {
    accounts.value = await getTreasuryAccounts();
  } catch {
    $q.notify({ type: "negative", message: "Erro ao carregar os bancos." });
  } finally {
    loading.value = false;
  }
};

const fetchLaunches = async () => {
  try {
    const params = selectedBank.value.account
      ? { account_id: selectedBank.value.account.id }
      : {};
    launches.value = await getTreasuryLaunches(params);
  } catch {
    $q.notify({ type: "negative", message: "Erro ao carregar o extrato." });
  }
};

const openCreateDialog = () => {
  $q.dialog({ component: AddEditTreasuryAccountDialog }).onOk(() => {
    $q.notify({ type: "positive", message: "Banco cadastrado com sucesso." });
    fetchAccounts();
  });
};

const openEditDialog = (account) => {
  $q.dialog({ component: AddEditTreasuryAccountDialog, componentProps: { account } }).onOk(() => {
    $q.notify({ type: "positive", message: "Banco atualizado com sucesso." });
    fetchAccounts();
  });
};

const handleAddItem = () => {
  if (!selectedBank.value.account) {
    $q.notify({ type: "warning", message: "Selecione um banco para lançar uma movimentação." });
    return;
  }

  $q.dialog({
    component: AddTreasuryLaunchDialog,
    componentProps: { account: selectedBank.value.account },
  }).onOk(() => {
    $q.notify({ type: "positive", message: "Movimentação registrada com sucesso." });
    fetchLaunches();
    fetchAccounts();
  });
};

const handleEditLaunch = (launch) => {
  const account = accounts.value.find((item) => item.id === launch.account_id);

  if (!account) {
    $q.notify({ type: "negative", message: "Banco da movimentação não encontrado." });
    return;
  }

  $q.dialog({
    component: AddTreasuryLaunchDialog,
    componentProps: { account, launch },
  }).onOk(() => {
    $q.notify({ type: "positive", message: "Movimentação atualizada com sucesso." });
    fetchLaunches();
    fetchAccounts();
  });
};

const handleDeleteLaunch = (launch) => {
  $q.dialog({
    title: "Excluir movimentação",
    message: `Deseja excluir a movimentação "${launch.description}"?`,
    ok: { color: "negative", label: "Excluir" },
    cancel: { color: "primary", outline: true, label: "Cancelar" },
  }).onOk(async () => {
    deletingId.value = launch.id;
    try {
      await deleteTreasuryLaunch(launch.id);
      $q.notify({ type: "positive", message: "Movimentação excluída com sucesso." });
      await Promise.all([fetchLaunches(), fetchAccounts()]);
    } catch {
      $q.notify({ type: "negative", message: "Erro ao excluir a movimentação." });
    } finally {
      deletingId.value = null;
    }
  });
};

watch(selectedBank, fetchLaunches);

onMounted(async () => {
  await fetchAccounts();
  await fetchLaunches();
});
</script>
