<template>
  <q-page class="owner-dashboard-page">
    <DefaultHeaderPage />

    <div class="dashboard-shell">
      <q-banner
        v-if="!hasProperties"
        class="bg-surface text-text radius-8"
        rounded
      >
        Nenhum imóvel vinculado ao proprietário autenticado.
      </q-banner>

      <template v-else>
        <DashboardFiltersBar
          action-label="Voltar ao dashboard"
          title="Despesas"
          :loading="loading"
          :month-options="monthOptions"
          :property-options="propertyOptions"
          :selected-month="selectedMonth"
          :selected-property-option="selectedPropertyOption"
          :selected-year="selectedYear"
          :show-export="false"
          :year-options="yearOptions"
          @action="goToDashboard"
          @update:month="handleMonthChange"
          @update:property="handlePropertyChange"
          @update:year="handleYearChange"
        />

        <q-separator class="dashboard-separator" />

        <div class="section-header">
          <span class="dashboard-section-caption">Indicadores</span>
        </div>

        <div class="metrics-grid">
          <DashboardMetricCard
            v-for="card in firstRowCards"
            :key="card.label"
            :caption="card.caption"
            :label="card.label"
            :nowrap-caption="card.nowrapCaption"
            :value="card.value"
            variant="primary"
          />
        </div>

        <div class="section-header">
          <span class="dashboard-section-caption">Financeiro</span>
        </div>

        <div class="metrics-grid">
          <DashboardMetricCard
            v-for="card in secondRowCards"
            :key="card.label"
            :caption="card.caption"
            :label="card.label"
            :nowrap-caption="card.nowrapCaption"
            :value="card.value"
            variant="secondary"
          />
        </div>

        <div class="expenses-grid">
          <q-card flat class="panel-card panel-card--soft expenses-panel">
            <div class="panel-title">Despesas do Período</div>

            <DashboardPayoutTable
              :columns="expenseTableColumns"
              empty-label="Nenhuma despesa encontrada para o período."
              row-key="key"
              :rows="expenseTableRows"
              total-label="Total de despesas"
              :total-row="expenseTableTotalRow"
            />
          </q-card>

          <q-card flat class="panel-card panel-card--soft expenses-panel">
            <div class="panel-title">Manutenções do Período</div>

            <DashboardPayoutTable
              :columns="expenseTableColumns"
              empty-label="Nenhuma manutenção encontrada para o período."
              row-key="key"
              :rows="maintenanceTableRows"
              total-label="Total de manutenções"
              :total-row="maintenanceTableTotalRow"
            />
          </q-card>
        </div>
      </template>

      <q-inner-loading :showing="loading">
        <q-spinner color="primary" size="48px" />
      </q-inner-loading>
    </div>
  </q-page>
</template>

<script setup>
import { computed, onMounted, ref } from "vue";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";

import { getOwnerDashboard } from "src/api/ownerDashboard";
import { buildMetricCards as buildDashboardMetricCards } from "src/helpers/buildMetricCards";

import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
import DashboardFiltersBar from "./components/DashboardFiltersBar.vue";
import DashboardMetricCard from "./components/DashboardMetricCard.vue";
import DashboardPayoutTable from "./components/DashboardPayoutTable.vue";

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

const dashboard = ref(null);
const loading = ref(false);
const selectedPropertyOption = ref(null);
const selectedMonth = ref(null);
const selectedYear = ref(null);
const dashboardRequestId = ref(0);

const defaultSummary = Object.freeze({
  reserve_total: 0,
  total_forward_fee_all: 0,
  owner_payout_amount: 0,
  final_payout_amount: 0,
  total_expenses_amount: 0,
  occupied_nights_in_month: 0,
  occupancy_rate: 0,
  average_price_per_night: null,
  average_reservation_ticket: null,
  average_nights_per_reservation: 0,
  maintenance_days: 0,
  cleanings_count: 0,
  expenses: 0,
  reservations_count: 0,
  distinct_reservations_count: 0,
  checkout_reservations_count: 0,
  crossed_reservations_count: 0,
  repeated_reservations_count: 0,
  crossed_cleanings_count: 0,
  repeated_cleanings_count: 0,
  available_days: 0,
  days_in_month: 30,
  properties_count: 1,

  gross_revenue: 0,
  ota_amount: 0,
  net_revenue_amount: 0,
  cleaning_total_amount: 0,
  management_fee_amount: 0,
  expenses_amount: 0,
  manual_expenses_amount: 0,
  payout_amount: 0,
  expenses_breakdown: {
    items: [],
    system_expenses: [],
    totals: {
      expenses_amount: 0,
      manual_expenses_amount: 0,
      system_expenses_amount: 0,
    },
  },
});

const monthLabels = [
  "Janeiro",
  "Fevereiro",
  "Março",
  "Abril",
  "Maio",
  "Junho",
  "Julho",
  "Agosto",
  "Setembro",
  "Outubro",
  "Novembro",
  "Dezembro",
];

const availableReferences = computed(
  () => dashboard.value?.filters?.available_references ?? [],
);

const selectedFilters = computed(
  () => dashboard.value?.filters?.selected ?? {},
);

const propertyOptions = computed(() => {
  const properties = dashboard.value?.filters?.properties ?? [];

  return [
    { id: null, label: "Todos os imóveis" },
    ...properties.map((property) => ({
      id: property.id,
      label: property.label,
    })),
  ];
});

const hasProperties = computed(() => propertyOptions.value.length > 1);

const selectedPropertyId = computed(() => {
  return selectedPropertyOption.value?.id ?? null;
});

const isAllPropertiesSelected = computed(
  () => selectedPropertyId.value === null,
);

const summary = computed(() => dashboard.value?.summary ?? defaultSummary);

const totalCapacityDays = computed(() =>
  Math.max(
    1,
    Number(summary.value.days_in_month ?? 0) *
      Number(summary.value.properties_count ?? 1),
  ),
);

const yearOptions = computed(() => {
  const years = [
    ...new Set(
      availableReferences.value.map((reference) => reference.reference_year),
    ),
  ];

  return years
    .sort((a, b) => b - a)
    .map((year) => ({
      label: String(year),
      value: year,
    }));
});

const monthOptions = computed(() => {
  if (!selectedYear.value) {
    return [];
  }

  const months = [
    ...new Set(
      availableReferences.value
        .filter((reference) => reference.reference_year === selectedYear.value)
        .map((reference) => reference.reference_month),
    ),
  ];

  return months
    .sort((a, b) => a - b)
    .map((month) => ({
      label: monthLabels[month - 1] ?? String(month),
      value: month,
    }));
});

const selectedReferenceLabel = computed(() => {
  if (!selectedMonth.value || !selectedYear.value) {
    return "Mês selecionado";
  }

  const monthLabel =
    monthLabels[selectedMonth.value - 1] ?? String(selectedMonth.value);

  return `${monthLabel} ${selectedYear.value}`;
});

const allMetricCards = computed(() =>
  buildDashboardMetricCards(summary.value, {
    isAllPropertiesSelected: isAllPropertiesSelected.value,
    referenceLabel: selectedReferenceLabel.value,
    totalCapacityDays: totalCapacityDays.value,
  }),
);

const firstRowCards = computed(() => allMetricCards.value.slice(0, 7));

const secondRowCards = computed(() => allMetricCards.value.slice(7, 14));

const manualExpenseRows = computed(
  () =>
    summary.value?.expenses_breakdown?.items?.filter(
      (expense) => expense.source === "manual",
    ) ?? [],
);

const resolveExpenseType = (expense) => expense.type ?? expense.category;

const expenseRows = computed(() =>
  manualExpenseRows.value.filter(
    (expense) => resolveExpenseType(expense) === "expense",
  ),
);

const maintenanceRows = computed(() =>
  manualExpenseRows.value.filter(
    (expense) => resolveExpenseType(expense) === "maintenance",
  ),
);

const sumExpenseRows = (rows) =>
  rows.reduce((total, expense) => total + Number(expense.final_amount ?? 0), 0);

const expenseTotal = computed(() => sumExpenseRows(expenseRows.value));

const maintenanceTotal = computed(() => sumExpenseRows(maintenanceRows.value));

const expenseTableColumns = [
  {
    key: "label",
    label: "Despesa",
    type: "text",
    direction: null,
  },
  {
    key: "source_label",
    label: "Origem",
    type: "text",
    direction: null,
  },
  {
    key: "final_amount",
    label: "Valor",
    type: "currency",
    direction: null,
  },
];

const expenseTableRows = computed(() =>
  expenseRows.value.map((expense, index) => ({
    ...expense,
    key: expense.key || `${expense.label}-${index}`,
    source_label: expense.source === "manual" ? "Interna" : "Stays/Sistema",
  })),
);

const maintenanceTableRows = computed(() =>
  maintenanceRows.value.map((expense, index) => ({
    ...expense,
    key: expense.key || `${expense.label}-${index}`,
    source_label: expense.source === "manual" ? "Interna" : "Stays/Sistema",
  })),
);

const expenseTableTotalRow = computed(() => ({
  source_label: "",
  final_amount: expenseTotal.value,
}));

const maintenanceTableTotalRow = computed(() => ({
  source_label: "",
  final_amount: maintenanceTotal.value,
}));

const buildDashboardParams = ({ year, month, propertyId } = {}) => {
  const params = {};

  if (year) {
    params.year = year;
  }

  if (month) {
    params.month = month;
  }

  if (propertyId !== null && propertyId !== undefined) {
    params.property_id = propertyId;
  }

  return params;
};

const updateRouteQuery = () => {
  router.replace({
    name: "DashboardExpensesPage",
    query: {
      year: selectedYear.value ?? undefined,
      month: selectedMonth.value ?? undefined,
      property_id: selectedPropertyId.value ?? undefined,
    },
  });
};

const findPropertyOptionById = (propertyId) => {
  return (
    propertyOptions.value.find((option) => option.id === propertyId) ??
    propertyOptions.value[0] ??
    null
  );
};

const fetchDashboard = async ({ year, month, propertyId } = {}) => {
  const requestId = ++dashboardRequestId.value;

  loading.value = true;

  try {
    const payload = await getOwnerDashboard(
      buildDashboardParams({ year, month, propertyId }),
    );

    if (requestId !== dashboardRequestId.value) {
      return;
    }

    dashboard.value = payload;

    selectedPropertyOption.value = findPropertyOptionById(
      payload.filters.selected?.property_id ?? null,
    );
    selectedMonth.value = payload.filters.selected?.reference_month ?? null;
    selectedYear.value = payload.filters.selected?.reference_year ?? null;

    updateRouteQuery();
  } catch (error) {
    if (requestId !== dashboardRequestId.value) {
      return;
    }

    $q.notify({
      type: "negative",
      message:
        error?.response?.data?.message ??
        "Não foi possível carregar as despesas do proprietário.",
    });
  } finally {
    if (requestId === dashboardRequestId.value) {
      loading.value = false;
    }
  }
};

const handleMonthChange = async (month) => {
  if (month === selectedFilters.value.reference_month) {
    return;
  }

  await fetchDashboard({
    year: selectedYear.value,
    month,
    propertyId: selectedPropertyId.value,
  });
};

const handleYearChange = async (year) => {
  const availableMonth =
    availableReferences.value
      .filter((reference) => reference.reference_year === year)
      .sort((a, b) => b.reference_month - a.reference_month)[0]
      ?.reference_month ?? selectedMonth.value;

  if (
    year === selectedFilters.value.reference_year &&
    availableMonth === selectedFilters.value.reference_month
  ) {
    return;
  }

  await fetchDashboard({
    year,
    month: availableMonth,
    propertyId: selectedPropertyId.value,
  });
};

const handlePropertyChange = async (propertyOption) => {
  const nextPropertyId = propertyOption?.id ?? null;
  const currentPropertyId = selectedFilters.value.property_id ?? null;

  if (nextPropertyId === currentPropertyId) {
    return;
  }

  await fetchDashboard({
    year: selectedYear.value,
    month: selectedMonth.value,
    propertyId: nextPropertyId,
  });
};

const goToDashboard = () => {
  router.push({
    name: "DashboardPage",
    query: {
      year: selectedYear.value ?? undefined,
      month: selectedMonth.value ?? undefined,
      property_id: selectedPropertyId.value ?? undefined,
    },
  });
};

const resolveInitialNumber = (value) => {
  const numberValue = Number(value);

  return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : null;
};

onMounted(async () => {
  await fetchDashboard({
    year: resolveInitialNumber(route.query.year),
    month: resolveInitialNumber(route.query.month),
    propertyId: resolveInitialNumber(route.query.property_id),
  });
});
</script>

<style scoped lang="scss">
.owner-dashboard-page {
  position: relative;
}

.dashboard-shell {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

.dashboard-separator {
  margin-top: -4px;
  background: rgba(8, 81, 76, 0.12);
}

.dashboard-section-caption {
  margin-top: -2px;
  margin-bottom: -4px;
  color: #08514c;
  font-size: 19px;
  font-weight: 400;
  line-height: 1.1;
  vertical-align: middle;
}

.section-header {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 10px;
  min-width: 0;
  align-items: stretch;
}

.panel-card {
  padding: 18px;
  border-radius: 14px;
  background: #ffffff;
  border: 1px solid #d9e3e7;
  min-height: 300px;
  min-width: 0;
  vertical-align: middle;
}

.panel-card--soft {
  background: #f0f3f5;
}

.expenses-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  min-width: 0;
}

.expenses-panel :deep(.payout-table th),
.expenses-panel :deep(.payout-table td),
.expenses-panel :deep(.payout-total-row td) {
  text-align: left;
}

.expenses-panel :deep(.header-wrapper) {
  align-items: flex-start;
}

.panel-title {
  margin-bottom: 16px;
  font-size: 19px;
  font-weight: 400;
  color: #08514c;
}

.owner-dashboard-page :deep(.text-h6.text-bold) {
  display: none;
}

@media (max-width: 1650px) {
  .metrics-grid {
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 8px;
  }
}

@media (max-width: 1450px) {
  .metrics-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

@media (max-width: 1100px) {
  .metrics-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 768px) {
  .metrics-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 640px) {
  .metrics-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .expenses-grid {
    grid-template-columns: 1fr;
  }
}
</style>
