<template>
  <v-card class="span-12 panel-pad">
    <div class="toolbar-row mb-3">
      <div>
        <h2 class="section-title">Activity &amp; audit trail</h2>
        <p class="quiet text-body-2">
          Complete record of user activity — sign-ins, lockouts, password and permission changes, and every data edit.
        </p>
      </div>
      <v-spacer />
      <v-btn variant="tonal" prepend-icon="mdi-download" :loading="exporting" @click="exportCsv">Export CSV</v-btn>
    </div>

    <div class="filter-grid mb-3">
      <v-select
        v-model="filters.actor"
        :items="actorItems"
        item-title="title"
        item-value="value"
        label="User"
        density="compact"
        hide-details
        clearable
      />
      <v-select
        v-model="filters.action"
        :items="facets.actions"
        label="Action"
        density="compact"
        hide-details
        clearable
      />
      <v-select
        v-model="filters.entity_type"
        :items="facets.entity_types"
        label="Entity type"
        density="compact"
        hide-details
        clearable
      />
      <v-text-field v-model="filters.from" type="date" label="From" density="compact" hide-details clearable />
      <v-text-field v-model="filters.to" type="date" label="To" density="compact" hide-details clearable />
      <v-text-field
        v-model="filters.q"
        label="Search"
        placeholder="entity, id, action…"
        density="compact"
        hide-details
        clearable
        prepend-inner-icon="mdi-magnify"
        @keyup.enter="applyFilters"
      />
    </div>
    <div class="toolbar-row mb-3">
      <v-btn size="small" color="primary" variant="tonal" prepend-icon="mdi-filter" @click="applyFilters">Apply filters</v-btn>
      <v-btn size="small" variant="text" @click="resetFilters">Reset</v-btn>
      <v-spacer />
      <span class="quiet text-body-2">{{ total }} event{{ total === 1 ? '' : 's' }}</span>
    </div>

    <v-alert v-if="error" type="error" density="compact" class="mb-3">{{ error }}</v-alert>

    <v-table density="compact" class="audit-table">
      <thead>
        <tr>
          <th>Time</th>
          <th>User</th>
          <th>Action</th>
          <th>Entity</th>
          <th>ID</th>
          <th>Details</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="row in rows" :key="row.id">
          <td class="nowrap">{{ shortDate(row.created_at) }}</td>
          <td>{{ row.actor_name || (row.actor_id ? `#${row.actor_id}` : 'System') }}</td>
          <td><v-chip size="x-small" variant="tonal" :color="actionColor(row.action)">{{ row.action }}</v-chip></td>
          <td>{{ row.entity_type }}</td>
          <td class="nowrap">{{ row.entity_id || '—' }}</td>
          <td>
            <v-menu v-if="row.before_json || row.after_json" location="start">
              <template #activator="{ props }">
                <v-btn v-bind="props" size="x-small" variant="text" icon="mdi-information-outline" />
              </template>
              <v-card class="detail-card pa-3">
                <div v-if="row.before_json" class="mb-2">
                  <div class="quiet text-caption mb-1">Before</div>
                  <pre class="detail-json">{{ pretty(row.before_json) }}</pre>
                </div>
                <div v-if="row.after_json">
                  <div class="quiet text-caption mb-1">After</div>
                  <pre class="detail-json">{{ pretty(row.after_json) }}</pre>
                </div>
              </v-card>
            </v-menu>
            <span v-else class="quiet">—</span>
          </td>
        </tr>
        <tr v-if="!rows.length && !loading">
          <td colspan="6" class="text-center quiet py-4">No activity matches these filters.</td>
        </tr>
      </tbody>
    </v-table>

    <div class="toolbar-row mt-3">
      <v-spacer />
      <v-pagination
        v-if="pageCount > 1"
        v-model="page"
        :length="pageCount"
        :total-visible="5"
        density="compact"
        @update:model-value="load"
      />
    </div>
  </v-card>
</template>

<script>
import { apiRequest, saveBlob } from '../services/api';
import { shortDate } from '../utils/format';

// Activity & Audit Trail viewer (Admin → Activity & Audit Trail). Server-side paginated + filtered
// (user/action/entity-type/date/search); filter dropdown options come from the `facets` the list
// endpoint returns. Uses its own table + pager rather than DataTable because that paginates client-side.

const BLANK_FILTERS = { actor: null, action: null, entity_type: null, from: null, to: null, q: '' };

export default {
  props: {
    token: { type: String, required: true }
  },
  data() {
    return {
      filters: { ...BLANK_FILTERS },
      rows: [],
      facets: { actions: [], entity_types: [], actors: [] },
      total: 0,
      page: 1,
      pageSize: 25,
      loading: false,
      exporting: false,
      error: ''
    };
  },
  computed: {
    pageCount() {
      return Math.max(1, Math.ceil(this.total / this.pageSize));
    },
    actorItems() {
      return this.facets.actors.map((a) => ({ title: a.name || `#${a.id}`, value: a.id }));
    }
  },
  mounted() {
    this.load();
  },
  methods: {
    shortDate,
    async api(path, options = {}) {
      return apiRequest(path, this.token, options);
    },
    queryString() {
      const params = new URLSearchParams();
      for (const [key, value] of Object.entries(this.filters)) {
        if (value !== null && value !== '' && value !== undefined) params.set(key, value);
      }
      return params;
    },
    async load() {
      this.loading = true;
      this.error = '';
      try {
        const params = this.queryString();
        params.set('page', this.page);
        params.set('pageSize', this.pageSize);
        const data = await (await this.api(`/api/audit-logs?${params.toString()}`)).json();
        this.rows = data.rows;
        this.total = data.total;
        this.facets = data.facets;
      } catch (error) {
        this.error = error.message;
      } finally {
        this.loading = false;
      }
    },
    applyFilters() {
      this.page = 1;
      this.load();
    },
    resetFilters() {
      this.filters = { ...BLANK_FILTERS };
      this.page = 1;
      this.load();
    },
    async exportCsv() {
      this.exporting = true;
      this.error = '';
      try {
        const response = await this.api(`/api/audit-logs/export?${this.queryString().toString()}`);
        const blob = await response.blob();
        saveBlob(blob, `audit-trail-${new Date().toISOString().slice(0, 10)}.csv`);
      } catch (error) {
        this.error = error.message;
      } finally {
        this.exporting = false;
      }
    },
    pretty(jsonText) {
      try {
        return JSON.stringify(JSON.parse(jsonText), null, 2);
      } catch {
        return jsonText;
      }
    },
    actionColor(action) {
      if (/fail|locked|delete/.test(action)) return 'error';
      if (/login|create/.test(action)) return 'success';
      if (/update|change|export/.test(action)) return 'info';
      return undefined;
    }
  }
};
</script>

<style scoped>
.filter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
}
.audit-table .nowrap {
  white-space: nowrap;
}
.detail-card {
  max-width: 520px;
  max-height: 60vh;
  overflow: auto;
}
.detail-json {
  font-size: 11px;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
}
</style>
