<template>
  <h1>События</h1>
  <div class="filters">
    <input v-model="q" placeholder="Поиск в summary/title" @keyup.enter="applyFilters" />
    <select v-model="severity" @change="applyFilters">
      <option value="">Все severity</option>
      <option>info</option>
      <option>warning</option>
      <option>high</option>
      <option>critical</option>
    </select>
    <input v-model="typeFilter" placeholder="type" @keyup.enter="applyFilters" />
    <input v-model="hostnameFilter" placeholder="hostname / имя сервера" @keyup.enter="applyFilters" />
    <label class="events-date-field">
      <span class="events-date-label">С</span>
      <input v-model="dateFrom" type="date" @change="applyFilters" />
    </label>
    <label class="events-date-field">
      <span class="events-date-label">По</span>
      <input v-model="dateTo" type="date" @change="applyFilters" />
    </label>
    <button type="button" @click="applyFilters">Применить</button>
    <button v-if="hasActiveFilters" type="button" class="secondary" @click="clearFilters">Сбросить</button>
  </div>
  <p v-if="error" class="error">{{ error }}</p>
  <p v-else-if="loading">Загрузка…</p>
  <template v-else>
    <p>Всего: {{ data?.total ?? 0 }}</p>
    <table>
      <thead>
        <tr>
          <th>ID</th>
          <th>Время</th>
          <th>Хост</th>
          <th>Имя сервера</th>
          <th>Пользователь</th>
          <th>Версия агента</th>
          <th>Severity</th>
          <th>Type</th>
          <th>Title</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="e in data?.items ?? []" :key="e.id">
          <td>
            <RouterLink :to="{ path: `/events/${e.id}`, query: detailLinkQuery }">{{ e.id }}</RouterLink>
          </td>
          <td>{{ formatDt(e.occurred_at) }}</td>
          <td>{{ e.hostname }}</td>
          <td>{{ formatServerName(e.display_name) }}</td>
          <td>{{ e.actor_user || "—" }}</td>
          <td>{{ e.product_version || "—" }}</td>
          <td :class="'sev-' + e.severity">{{ e.severity }}</td>
          <td><code>{{ e.type }}</code></td>
          <td>{{ e.title }}</td>
        </tr>
      </tbody>
    </table>
    <div class="filters" style="margin-top: 1rem">
      <button type="button" class="secondary" :disabled="page <= 1" @click="load(page - 1)">Назад</button>
      <span>Стр. {{ page }}</span>
      <button
        type="button"
        class="secondary"
        :disabled="!data || page * pageSize >= data.total"
        @click="load(page + 1)"
      >
        Вперёд
      </button>
    </div>
  </template>
</template>

<script setup lang="ts">
import { computed, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { apiFetch, type EventListResponse } from "../api";
import {
  apiParamsFromState,
  buildEventsListQuery,
  eventsListQueryMatches,
  parseEventsListQuery,
  type EventsListState,
} from "../utils/eventsListQuery";
import { formatServerName } from "../utils/hostDisplay";

const route = useRoute();
const router = useRouter();

const data = ref<EventListResponse | null>(null);
const loading = ref(false);
const error = ref("");
const page = ref(1);
const pageSize = 50;
const q = ref("");
const severity = ref("");
const typeFilter = ref("");
const hostnameFilter = ref("");
const dateFrom = ref("");
const dateTo = ref("");

const syncingFromRoute = ref(false);

const listState = computed(
  (): EventsListState => ({
    page: page.value,
    q: q.value,
    severity: severity.value,
    type: typeFilter.value,
    hostname: hostnameFilter.value,
    dateFrom: dateFrom.value,
    dateTo: dateTo.value,
  }),
);

const detailLinkQuery = computed(() => buildEventsListQuery(listState.value));

const hasActiveFilters = computed(
  () =>
    Boolean(
      q.value.trim() ||
        severity.value ||
        typeFilter.value.trim() ||
        hostnameFilter.value.trim() ||
        dateFrom.value ||
        dateTo.value,
    ),
);

function formatDt(iso: string) {
  return new Date(iso).toLocaleString("ru-RU");
}

function applyStateFromQuery() {
  const parsed = parseEventsListQuery(route.query);
  page.value = parsed.page;
  q.value = parsed.q;
  severity.value = parsed.severity;
  typeFilter.value = parsed.type;
  hostnameFilter.value = parsed.hostname;
  dateFrom.value = parsed.dateFrom;
  dateTo.value = parsed.dateTo;
}

async function syncRouteQuery() {
  if (eventsListQueryMatches(listState.value, route.query)) return;
  syncingFromRoute.value = true;
  try {
    await router.replace({ path: "/events", query: buildEventsListQuery(listState.value) });
  } finally {
    syncingFromRoute.value = false;
  }
}

async function load(p?: number, options?: { syncUrl?: boolean }) {
  if (p !== undefined) page.value = p;
  loading.value = true;
  error.value = "";
  try {
    const params = apiParamsFromState(listState.value, pageSize);
    data.value = await apiFetch<EventListResponse>(`/api/v1/events?${params}`);
    if (options?.syncUrl !== false && !syncingFromRoute.value) {
      await syncRouteQuery();
    }
  } catch (e) {
    error.value = e instanceof Error ? e.message : "Ошибка загрузки";
  } finally {
    loading.value = false;
  }
}

function applyFilters() {
  load(1);
}

function clearFilters() {
  q.value = "";
  severity.value = "";
  typeFilter.value = "";
  hostnameFilter.value = "";
  dateFrom.value = "";
  dateTo.value = "";
  load(1);
}

watch(
  () => route.fullPath,
  async () => {
    if (route.path !== "/events") return;
    const matched = eventsListQueryMatches(listState.value, route.query);
    if (!matched) {
      syncingFromRoute.value = true;
      applyStateFromQuery();
      syncingFromRoute.value = false;
    }
    if (!matched || !data.value) {
      await load(undefined, { syncUrl: false });
    }
  },
  { immediate: true },
);
</script>

<style scoped>
.events-date-field {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.events-date-label {
  color: #9aa4b2;
  font-size: 0.9rem;
  white-space: nowrap;
}

.events-date-field input[type="date"] {
  min-width: 9.5rem;
}
</style>
