<template>
  <div class="club-history-page">
    <header class="page-header card">
      <div>
        <p class="page-eyebrow">TT-Verein</p>
        <h2>Historie</h2>
        <p class="page-subtitle">
          Letzte Vorgänge aus Anfragen und Aufgaben für den Vereinsalltag in einer gemeinsamen Übersicht.
        </p>
      </div>
      <button type="button" class="btn-secondary" @click="loadHistory" :disabled="loading">
        {{ loading ? 'Lädt…' : 'Neu laden' }}
      </button>
    </header>

    <section v-if="!currentClub" class="card empty-state">
      <h3>Kein Verein ausgewählt</h3>
      <p>Bitte zuerst einen Verein auswählen, um die Vereinshistorie zu sehen.</p>
    </section>

    <template v-else>
      <section class="history-stats-grid">
        <article class="card stat-card">
          <span class="stat-label">Einträge</span>
          <strong class="stat-value">{{ historyStats.total }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Heute</span>
          <strong class="stat-value">{{ historyStats.today }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Offene Aufgaben</span>
          <strong class="stat-value">{{ historyStats.openTasks }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Offene Anfragen</span>
          <strong class="stat-value">{{ historyStats.openRequests }}</strong>
        </article>
      </section>

      <section class="history-layout">
        <aside class="card history-sidebar">
          <div class="section-header">
            <h3>Filter</h3>
          </div>
          <div class="history-filter-stack">
            <label>
              <span>Quelle</span>
              <select v-model="filters.source">
                <option value="">Alle</option>
                <option value="request">Anfragen</option>
                <option value="request_note">Notizen</option>
                <option value="task">Aufgaben</option>
                <option value="task_done">Erledigungen</option>
                <option value="role">Rollen</option>
                <option value="user">Benutzer</option>
                <option value="role_assignment">Rollenzuweisungen</option>
              </select>
            </label>
            <label>
              <span>Suche</span>
              <input v-model.trim="filters.search" type="text" placeholder="Titel, Person oder Beschreibung" />
            </label>
          </div>

          <div class="history-note-box">
            <h4>Stand heute</h4>
            <p>
              Diese erste Historie nutzt bereits echte Vereinsdaten. Feldgenaue Änderungen mit
              altem und neuem Wert folgen im nächsten Ausbauschritt.
            </p>
          </div>
        </aside>

        <section class="card history-list-card">
          <div class="section-header">
            <h3>Letzte Vorgänge</h3>
            <span class="history-count">{{ filteredEntries.length }} Einträge</span>
          </div>

          <p v-if="loadError" class="state-banner state-banner-error">{{ loadError }}</p>
          <p v-else-if="loading" class="state-banner">Historie wird geladen…</p>
          <p v-else-if="filteredEntries.length === 0" class="state-banner">Keine Einträge im aktuellen Filter.</p>

          <div v-else class="history-list">
            <article
              v-for="entry in filteredEntries"
              :key="entry.key"
              class="history-entry"
            >
              <div class="history-entry-main">
                <div class="history-entry-topline">
                  <span class="history-source-badge" :class="`source-${entry.source}`">{{ entry.sourceLabel }}</span>
                  <strong>{{ entry.title }}</strong>
                </div>
                <p class="history-entry-description">{{ entry.description }}</p>
                <p class="history-entry-meta">
                  <span>{{ formatDateTime(entry.occurredAt) }}</span>
                  <span v-if="entry.personLabel">{{ entry.personLabel }}</span>
                  <span v-if="entry.statusLabel">{{ entry.statusLabel }}</span>
                </p>
              </div>
              <button type="button" class="btn-secondary" @click="openEntry(entry)">
                Öffnen
              </button>
            </article>
          </div>
        </section>
      </section>
    </template>
  </div>
</template>

<script>
import { mapGetters } from 'vuex';
import apiClient from '../apiClient.js';
import { safeErrorMessage } from '../utils/dialogUtils.js';

function normalizeTask(payload = {}) {
  return {
    id: payload.id,
    title: payload.title || '',
    description: payload.description || '',
    taskType: payload.taskType || payload.task_type || '',
    status: payload.status || 'open',
    priority: payload.priority || 'normal',
    dueAt: payload.dueAt || payload.due_at || null,
    completedAt: payload.completedAt || payload.completed_at || null,
    createdAt: payload.createdAt || payload.created_at || null,
    updatedAt: payload.updatedAt || payload.updated_at || null,
  };
}

function normalizeRequest(payload = {}) {
  return {
    id: payload.id,
    requestType: payload.requestType || payload.request_type || 'contact',
    status: payload.status || 'open',
    workflowStage: payload.workflowStage || payload.workflow_stage || '',
    subject: payload.subject || '',
    firstName: payload.firstName || payload.first_name || '',
    lastName: payload.lastName || payload.last_name || '',
    email: payload.email || '',
    message: payload.message || '',
    receivedAt: payload.receivedAt || payload.received_at || payload.createdAt || payload.created_at || null,
    createdAt: payload.createdAt || payload.created_at || null,
    updatedAt: payload.updatedAt || payload.updated_at || null,
    notes: Array.isArray(payload.notes)
      ? payload.notes.map((note) => ({
          id: note.id,
          body: note.body || '',
          createdAt: note.createdAt || note.created_at || null,
        }))
      : [],
  };
}

function normalizeRole(payload = {}) {
  return {
    id: payload.id,
    roleKey: payload.roleKey || payload.role_key || '',
    name: payload.name || '',
    description: payload.description || '',
    isSystemRole: payload.isSystemRole === true || payload.isSystemRole === 1 || payload.isSystemRole === '1' || payload.isSystemRole === 'true',
    createdAt: payload.createdAt || payload.created_at || null,
    updatedAt: payload.updatedAt || payload.updated_at || null,
  };
}

function normalizeMemberRole(payload = {}) {
  return {
    id: payload.id || null,
    roleKey: payload.roleKey || payload.role_key || '',
    name: payload.name || '',
    isPrimary: Boolean(payload.isPrimary),
    assignedAt: payload.assignedAt || payload.assigned_at || payload.createdAt || payload.created_at || null,
    assignmentUpdatedAt: payload.assignmentUpdatedAt || payload.assignment_updated_at || payload.updatedAt || payload.updated_at || null,
  };
}

function normalizeClubUser(payload = {}) {
  return {
    userId: payload.userId,
    user: payload.user || null,
    approved: payload.approved !== false,
    isOwner: Boolean(payload.isOwner),
    createdAt: payload.createdAt || payload.created_at || null,
    updatedAt: payload.updatedAt || payload.updated_at || null,
    roles: Array.isArray(payload.roles) ? payload.roles.map(normalizeMemberRole) : [],
  };
}

function sameMoment(a, b) {
  if (!a || !b) return false;
  return new Date(a).getTime() === new Date(b).getTime();
}

export default {
  name: 'ClubHistoryView',
  data() {
    return {
      loading: false,
      loadError: '',
      tasks: [],
      requests: [],
      clubRoles: [],
      clubUsers: [],
      filters: {
        source: '',
        search: '',
      },
    };
  },
  computed: {
    ...mapGetters(['currentClub']),
    historyEntries() {
      const entries = [];

      this.requests.forEach((request) => {
        const requestLabel = this.requestDisplayLabel(request);
        entries.push({
          key: `request-created-${request.id}`,
          source: 'request',
          sourceLabel: 'Anfrage',
          occurredAt: request.receivedAt || request.createdAt,
          title: request.subject || requestLabel,
          description: `${requestLabel} eingegangen`,
          personLabel: this.requestPersonLabel(request),
          statusLabel: this.requestStatusLabel(request.status),
          to: '/club-requests',
        });

        if (request.updatedAt && !sameMoment(request.updatedAt, request.createdAt) && !sameMoment(request.updatedAt, request.receivedAt)) {
          entries.push({
            key: `request-updated-${request.id}`,
            source: 'request',
            sourceLabel: 'Anfrage',
            occurredAt: request.updatedAt,
            title: request.subject || requestLabel,
            description: 'Anfrage aktualisiert',
            personLabel: this.requestPersonLabel(request),
            statusLabel: this.requestStatusLabel(request.status),
            to: '/club-requests',
          });
        }

        request.notes.forEach((note) => {
          entries.push({
            key: `request-note-${request.id}-${note.id || note.createdAt}`,
            source: 'request_note',
            sourceLabel: 'Notiz',
            occurredAt: note.createdAt,
            title: request.subject || requestLabel,
            description: note.body || 'Interne Notiz hinzugefügt',
            personLabel: this.requestPersonLabel(request),
            statusLabel: this.requestStatusLabel(request.status),
            to: '/club-requests',
          });
        });
      });

      this.tasks.forEach((task) => {
        const taskTypeLabel = this.taskTypeLabel(task.taskType);
        entries.push({
          key: `task-created-${task.id}`,
          source: 'task',
          sourceLabel: 'Aufgabe',
          occurredAt: task.createdAt,
          title: task.title || 'Aufgabe',
          description: `${taskTypeLabel} angelegt`,
          personLabel: '',
          statusLabel: this.taskStatusLabel(task.status),
          to: '/club-tasks',
        });

        if (task.completedAt) {
          entries.push({
            key: `task-done-${task.id}`,
            source: 'task_done',
            sourceLabel: 'Erledigung',
            occurredAt: task.completedAt,
            title: task.title || 'Aufgabe',
            description: 'Aufgabe erledigt',
            personLabel: '',
            statusLabel: this.taskStatusLabel(task.status),
            to: '/club-tasks',
          });
        } else if (task.updatedAt && !sameMoment(task.updatedAt, task.createdAt)) {
          entries.push({
            key: `task-updated-${task.id}`,
            source: 'task',
            sourceLabel: 'Aufgabe',
            occurredAt: task.updatedAt,
            title: task.title || 'Aufgabe',
            description: 'Aufgabe aktualisiert',
            personLabel: '',
            statusLabel: this.taskStatusLabel(task.status),
            to: '/club-tasks',
          });
        }
      });

      this.clubRoles.forEach((role) => {
        entries.push({
          key: `role-created-${role.id}`,
          source: 'role',
          sourceLabel: 'Rolle',
          occurredAt: role.createdAt,
          title: role.name || 'Rolle',
          description: role.isSystemRole ? 'Systemrolle verfügbar' : 'Rolle angelegt',
          personLabel: '',
          statusLabel: role.roleKey || '',
          to: '/club-roles',
        });

        if (role.updatedAt && !sameMoment(role.updatedAt, role.createdAt)) {
          entries.push({
            key: `role-updated-${role.id}`,
            source: 'role',
            sourceLabel: 'Rolle',
            occurredAt: role.updatedAt,
            title: role.name || 'Rolle',
            description: 'Rolle oder Rechte aktualisiert',
            personLabel: '',
            statusLabel: role.roleKey || '',
            to: '/club-roles',
          });
        }
      });

      this.clubUsers.forEach((member) => {
        const email = member.user?.email || `Benutzer ${member.userId}`;
        entries.push({
          key: `user-linked-${member.userId}`,
          source: 'user',
          sourceLabel: 'Benutzer',
          occurredAt: member.createdAt,
          title: email,
          description: 'Benutzer dem Verein zugeordnet',
          personLabel: '',
          statusLabel: member.approved ? 'Aktiv' : 'Inaktiv',
          to: '/club-users',
        });

        if (member.updatedAt && !sameMoment(member.updatedAt, member.createdAt)) {
          entries.push({
            key: `user-updated-${member.userId}`,
            source: 'user',
            sourceLabel: 'Benutzer',
            occurredAt: member.updatedAt,
            title: email,
            description: member.approved ? 'Benutzerzugang oder Rechte aktualisiert' : 'Benutzer deaktiviert',
            personLabel: '',
            statusLabel: member.approved ? 'Aktiv' : 'Inaktiv',
            to: '/club-users',
          });
        }

        member.roles.forEach((role) => {
          entries.push({
            key: `role-assignment-${member.userId}-${role.id || role.roleKey}-${role.assignedAt}`,
            source: 'role_assignment',
            sourceLabel: 'Zuweisung',
            occurredAt: role.assignedAt,
            title: role.name || role.roleKey || 'Rolle',
            description: `Rolle ${role.isPrimary ? 'primär ' : ''}zugewiesen`,
            personLabel: email,
            statusLabel: role.roleKey || '',
            to: '/club-users',
          });
        });
      });

      return entries
        .filter((entry) => entry.occurredAt)
        .sort((left, right) => new Date(right.occurredAt) - new Date(left.occurredAt));
    },
    filteredEntries() {
      const search = this.filters.search.trim().toLowerCase();
      return this.historyEntries.filter((entry) => {
        if (this.filters.source && entry.source !== this.filters.source) {
          return false;
        }
        if (!search) {
          return true;
        }
        return [
          entry.title,
          entry.description,
          entry.personLabel,
          entry.statusLabel,
        ].join(' ').toLowerCase().includes(search);
      });
    },
    historyStats() {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      return {
        total: this.historyEntries.length,
        today: this.historyEntries.filter((entry) => new Date(entry.occurredAt) >= today).length,
        openTasks: this.tasks.filter((task) => !['done', 'cancelled', 'archived'].includes(task.status)).length,
        openRequests: this.requests.filter((request) => ['open', 'in_progress', 'waiting'].includes(request.status)).length,
      };
    },
  },
  watch: {
    currentClub: {
      immediate: true,
      async handler(newClub) {
        if (!newClub) {
          this.tasks = [];
          this.requests = [];
          this.clubRoles = [];
          this.clubUsers = [];
          return;
        }
        await this.loadHistory();
      },
    },
  },
  methods: {
    async loadHistory() {
      if (!this.currentClub) {
        return;
      }

      this.loading = true;
      this.loadError = '';

      try {
        const results = await Promise.allSettled([
          apiClient.get(`/club-tasks/${this.currentClub}`),
          apiClient.get(`/club-requests/${this.currentClub}`),
          apiClient.get(`/permissions/${this.currentClub}/roles`),
          apiClient.get(`/permissions/${this.currentClub}/members`),
        ]);

        const [tasksResult, requestsResult, rolesResult, membersResult] = results;

        const taskEntries = tasksResult.status === 'fulfilled'
          ? (Array.isArray(tasksResult.value.data?.tasks)
              ? tasksResult.value.data.tasks
              : Array.isArray(tasksResult.value.data)
                ? tasksResult.value.data
                : [])
          : [];
        const requestEntries = requestsResult.status === 'fulfilled'
          ? (Array.isArray(requestsResult.value.data)
              ? requestsResult.value.data
              : Array.isArray(requestsResult.value.data?.requests)
                ? requestsResult.value.data.requests
                : [])
          : [];
        const roleEntries = rolesResult.status === 'fulfilled' && Array.isArray(rolesResult.value.data)
          ? rolesResult.value.data
          : [];
        const memberEntries = membersResult.status === 'fulfilled' && Array.isArray(membersResult.value.data)
          ? membersResult.value.data
          : [];

        this.tasks = taskEntries.map(normalizeTask);
        this.requests = requestEntries.map(normalizeRequest);
        this.clubRoles = roleEntries.map(normalizeRole);
        this.clubUsers = memberEntries.map(normalizeClubUser);

        const blockingErrors = results
          .filter((result) => result.status === 'rejected')
          .map((result) => result.reason)
          .filter((error) => ![403, 404].includes(error?.response?.status));
        if (blockingErrors.length > 0 && this.historyEntries.length === 0) {
          this.loadError = safeErrorMessage(blockingErrors[0], 'Historie konnte nicht geladen werden.');
        }
      } catch (error) {
        this.loadError = safeErrorMessage(error, 'Historie konnte nicht geladen werden.');
      } finally {
        this.loading = false;
      }
    },
    openEntry(entry) {
      if (!entry?.to) {
        return;
      }
      this.$router.push(entry.to);
    },
    formatDateTime(value) {
      if (!value) return '–';
      const date = new Date(value);
      if (Number.isNaN(date.getTime())) return '–';
      return new Intl.DateTimeFormat('de-DE', {
        dateStyle: 'medium',
        timeStyle: 'short',
      }).format(date);
    },
    requestDisplayLabel(request) {
      return {
        contact: 'Kontaktanfrage',
        trial_training: 'Probetraining',
        membership: 'Mitgliedschaftsanfrage',
        sponsoring: 'Sponsoringanfrage',
      }[request.requestType] || 'Anfrage';
    },
    requestStatusLabel(status) {
      return {
        open: 'Offen',
        in_progress: 'In Bearbeitung',
        waiting: 'Wartend',
        converted: 'Überführt',
        rejected: 'Abgelehnt',
        archived: 'Archiviert',
      }[status] || status;
    },
    taskStatusLabel(status) {
      return {
        open: 'Offen',
        in_progress: 'In Bearbeitung',
        waiting: 'Wartend',
        done: 'Erledigt',
        cancelled: 'Abgebrochen',
        archived: 'Archiviert',
      }[status] || status;
    },
    taskTypeLabel(taskType) {
      return {
        request_followup: 'Anfrage-Folgeaufgabe',
        trial_training_preparation: 'Probetraining',
        membership_review: 'Mitgliedschaft',
        member_record_creation: 'Mitglied anlegen',
        fee_assignment: 'Beitrag zuordnen',
        sepa_collection_preparation: 'SEPA vorbereiten',
      }[taskType] || 'Aufgabe';
    },
    requestPersonLabel(request) {
      const fullName = [request.firstName, request.lastName].filter(Boolean).join(' ').trim();
      return fullName || request.email || '';
    },
  },
};
</script>

<style scoped>
.club-history-page {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.page-header,
.history-sidebar,
.history-list-card,
.stat-card {
  padding: 1.25rem;
}

.page-eyebrow {
  margin: 0 0 0.35rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primary-strong);
}

.page-header h2,
.section-header h3,
.history-note-box h4 {
  margin: 0;
}

.page-subtitle {
  margin: 0.5rem 0 0;
  color: var(--text-secondary);
  max-width: 70ch;
}

.empty-state {
  padding: 1.5rem;
}

.history-stats-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
}

.stat-card {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.stat-label {
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.stat-value {
  font-size: 1.7rem;
  line-height: 1;
}

.history-layout {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 1rem;
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.history-filter-stack {
  display: grid;
  gap: 0.9rem;
}

.history-filter-stack label,
.history-filter-stack span {
  display: block;
}

.history-filter-stack span {
  margin-bottom: 0.35rem;
  font-weight: 600;
}

.history-filter-stack input,
.history-filter-stack select {
  width: 100%;
}

.history-note-box {
  margin-top: 1rem;
  border-radius: 12px;
  padding: 1rem;
  background: rgba(24, 70, 54, 0.06);
  color: var(--text-secondary);
}

.history-note-box p {
  margin: 0.5rem 0 0;
}

.history-count {
  color: var(--text-secondary);
  font-size: 0.92rem;
}

.history-list {
  display: grid;
  gap: 0.85rem;
}

.history-entry {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem;
  border-radius: 14px;
  border: 1px solid rgba(20, 46, 74, 0.08);
  background: rgba(255, 255, 255, 0.72);
}

.history-entry-main {
  min-width: 0;
}

.history-entry-topline {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.history-source-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 700;
}

.source-request {
  background: rgba(198, 134, 28, 0.14);
  color: #9a6400;
}

.source-request_note {
  background: rgba(91, 75, 170, 0.14);
  color: #5540ad;
}

.source-task {
  background: rgba(20, 109, 76, 0.14);
  color: #146d4c;
}

.source-task_done {
  background: rgba(33, 118, 201, 0.14);
  color: #1f68b0;
}

.history-entry-description,
.history-entry-meta {
  margin: 0.45rem 0 0;
}

.history-entry-description {
  color: var(--text-primary);
}

.history-entry-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  color: var(--text-secondary);
  font-size: 0.9rem;
}

.state-banner {
  margin: 0;
  padding: 1rem;
  border-radius: 12px;
  background: rgba(20, 46, 74, 0.05);
  color: var(--text-secondary);
}

.state-banner-error {
  background: rgba(180, 44, 44, 0.12);
  color: #9e2f2f;
}

@media (max-width: 960px) {
  .history-layout {
    grid-template-columns: 1fr;
  }

  .history-stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 640px) {
  .history-stats-grid {
    grid-template-columns: 1fr;
  }

  .history-entry {
    flex-direction: column;
    align-items: stretch;
  }
}
</style>
