<template>
  <div class="activity-log-page">
    <div class="page-header">
      <div>
        <h1 class="page-title">Activity Log</h1>
        <p class="page-subtitle">
          Track all system activities and user actions
        </p>
      </div>
      <div>
        <ActionButton
          label="Export CSV"
          icon="pi pi-download"
          severity="secondary"
          size="medium"
          :loading="exporting"
          @click="exportLogs"
        />
      </div>
    </div>

    <div class="statistics-grid">
      <div v-for="stat in statistics" :key="stat.title" class="stat-card">
        <div class="stat-content">
          <div class="stat-info">
            <p class="stat-label">{{ stat.title }}</p>
            <h3 class="stat-value">{{ stat.value }}</h3>
          </div>
          <div class="stat-icon" :class="`stat-icon-${stat.color}`">
            <VIcon :icon="stat.icon" size="24" />
          </div>
        </div>
      </div>
    </div>

    <div class="page-content" @click="handleTableClick">
      <div class="toolbar">
        <div class="search-section">
          <SearchBox
            v-model="searchTerm"
            placeholder="Search by user..."
            :loading="loading"
            size="medium"
            @search="handleSearch"
            @clear="handleClearSearch"
          />
        </div>

        <div class="filter-section">
          <VSelect
            v-model="filterAction"
            :items="activityActions"
            item-title="title"
            item-value="value"
            label="Filter by Action"
            density="compact"
            variant="outlined"
            class="filter-select"
            hide-details
            @update:model-value="
              activityLogStore.updateSearchParams({
                page: 1,
                q: searchTerm,
                action: filterAction,
              })
            "
          />

          <ActionButton
            label="Clear Filters"
            severity="secondary"
            size="small"
            @click="clearFilters"
          />
        </div>
      </div>

      <ReusableDataTable
        :data="activityLogs"
        :columns="tableColumns"
        :loading="loading"
        :paginator="true"
        :lazy="true"
        :rows="pagination.per_page"
        :total-records="pagination.total"
        :first="(pagination.current_page - 1) * pagination.per_page"
        :rows-per-page-options="[10, 25, 50]"
        data-key="id"
        table-class="activity-log-table"
        @page="handlePageChange"
        @sort="handleSortChange"
      />
    </div>

    <ReusableDialog
      v-model="showDetailsModal"
      title="Full Activity Details"
      max-width="800"
      fullscreen-on-mobile
    >
      <div class="dialog-content-grey">
        <p class="header-subtitle-alt">
          Review all field changes made during this action
        </p>

        <div class="steps-wrapper">
          <div class="changes-list-container">
            <div
              v-for="(change, index) in selectedChanges"
              :key="index"
              class="compact-change-item"
            >
              <div class="change-label">{{ change.label }}</div>
              <div class="change-values">
                <span class="val-old">{{ change.oldVal }}</span>
                <span class="val-arrow">&rarr;</span>
                <span class="val-new">{{ change.newVal }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      <template #actions>
        <div style="width: 100%; display: flex; justify-content: flex-end">
          <ActionButton
            label="Close"
            severity="secondary"
            size="medium"
            @click="showDetailsModal = false"
          />
        </div>
      </template>
    </ReusableDialog>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from "vue";
import { storeToRefs } from "pinia";
import ActionButton from "@/components/ActionButton.vue";
import ReusableDataTable from "@/components/ReusableDataTable.vue";
import SearchBox from "@/components/SearchBox.vue";
import ReusableDialog from "@/components/ReusableDialog.vue";
import { useActivityLogStore } from "@/stores/activityLogStore";
import { useAuthStore } from "@/stores/authStore";

// Get authenticated user
const authStore = useAuthStore();
const { user } = storeToRefs(authStore);

// Get activity log store
const activityLogStore = useActivityLogStore();
const {
  activityLogs,
  loading,
  searchTerm,
  filterAction,
  pagination,
  exporting,
} = storeToRefs(activityLogStore);

// Modal State
const showDetailsModal = ref(false);
const selectedChanges = ref([]);

// Activity action types for filter
const activityActions = [
  { title: "All Actions", value: "" },
  { title: "Created", value: "Created" },
  { title: "Updated", value: "Updated" },
  { title: "Deleted", value: "Deleted" },
  { title: "Published", value: "Published" },
  { title: "Viewed", value: "Viewed" },
];

onMounted(async () => {
  await activityLogStore.fetchActivityLogs({ page: 1, per_page: 10 });
});

// Statistics
const statistics = computed(() => {
  const stats = activityLogStore.statistics;
  return [
    {
      title: "Total Activities",
      value: stats.totalActivities,
      icon: "bx-list-ul",
      color: "primary",
    },
    {
      title: "Today's Activities",
      value: stats.todayActivities,
      icon: "bx-calendar",
      color: "success",
    },
    {
      title: "Active Users",
      value: stats.activeUsers,
      icon: "bx-user-check",
      color: "info",
    },
  ];
});

// Helper: Escape HTML to prevent injection
const escapeHtml = (unsafe) => {
  return (unsafe || "")
    .toString()
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
};

// Helper: Deep parse nested API objects
const parseChanges = (changesObj) => {
  let parsed = [];
  const isObject = (v) =>
    typeof v === "object" && v !== null && !Array.isArray(v);

  const processDiff = (key, oldVal, newVal, prefix = "") => {
    const formattedKey = key
      .replace(/_/g, " ")
      .replace(/\b\w/g, (l) => l.toUpperCase());
    const displayLabel = prefix ? `${prefix} › ${formattedKey}` : formattedKey;

    if (isObject(oldVal) || isObject(newVal)) {
      const safeOld = isObject(oldVal) ? oldVal : {};
      const safeNew = isObject(newVal) ? newVal : {};
      const allKeys = new Set([
        ...Object.keys(safeOld),
        ...Object.keys(safeNew),
      ]);

      for (const k of allKeys) {
        processDiff(k, safeOld[k], safeNew[k], displayLabel);
      }
    } else {
      let oStr =
        oldVal === undefined || oldVal === null
          ? "None"
          : typeof oldVal === "object"
            ? JSON.stringify(oldVal)
            : String(oldVal);
      let nStr =
        newVal === undefined || newVal === null
          ? "None"
          : typeof newVal === "object"
            ? JSON.stringify(newVal)
            : String(newVal);

      if (oStr !== nStr) {
        parsed.push({ label: displayLabel, oldVal: oStr, newVal: nStr });
      }
    }
  };

  for (const [key, val] of Object.entries(changesObj)) {
    let oldVal = val?.old !== undefined ? val.old : "None";
    let newVal = val?.new !== undefined ? val.new : val;
    processDiff(key, oldVal, newVal);
  }
  return parsed;
};

// Handle clicks inside the datatable HTML content
const handleTableClick = (event) => {
  const btn = event.target.closest(".view-more-btn");
  if (btn) {
    const rowId = btn.getAttribute("data-row-id");
    const row = activityLogStore.activityLogs.find((r) => r.id == rowId);

    if (row && row.changes) {
      let changesObj = row.changes;
      if (typeof changesObj === "string") {
        try {
          changesObj = JSON.parse(changesObj);
        } catch (e) {}
      }

      selectedChanges.value = parseChanges(changesObj);
      showDetailsModal.value = true;
    }
  }
};

const tableColumns = [
  {
    field: "user_name",
    header: "User",
    sortable: true,
    formatter: (value) => value || "Unknown",
  },
  {
    field: "action",
    header: "Action",
    sortable: true,
    template: "badge",
    badgeSeverity: (value) => {
      const severityMap = {
        "Program.created": "success",
        "Program.updated": "info",
        "Program.deleted": "error",
        "Program.published": "success",
        "Program.viewed": "secondary",
      };
      return severityMap[value] || "info";
    },
  },
  {
    field: "details",
    header: "Details",
    sortable: false,
    template: "custom",
    customHTML: (row) => {
      if (row.action && row.action.endsWith(".updated") && row.changes) {
        let changesObj = row.changes;

        if (typeof changesObj === "string") {
          try {
            changesObj = JSON.parse(changesObj);
          } catch (e) {}
        }

        if (typeof changesObj === "object" && changesObj !== null) {
          const parsedChanges = parseChanges(changesObj);
          if (parsedChanges.length === 0) return row.description || "-";

          const maxVisible = 3;
          let itemsHTML = parsedChanges
            .slice(0, maxVisible)
            .map(
              (change) => `
            <div style="padding: 8px 12px; border-bottom: 1px solid #e2e8f0;">
              <div style="color: #003b6f; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px;">${escapeHtml(change.label)}</div>
              <div style="display: flex; flex-wrap: wrap; align-items: center; font-size: 13px; gap: 6px; word-break: break-word;">
                <span style="color: #ef4444; text-decoration: line-through; font-weight: 500;">${escapeHtml(change.oldVal)}</span>
                <span style="color: #94a3b8; font-weight: bold;">&rarr;</span>
                <span style="color: #10b981; font-weight: 600;">${escapeHtml(change.newVal)}</span>
              </div>
            </div>
          `,
            )
            .join("");

          let finalHTML = `<div style="background: white; border: 1px solid #e2e8f0; border-radius: 6px; overflow: hidden; display: flex; flex-direction: column; width: 100%;">`;
          finalHTML += itemsHTML;

          if (parsedChanges.length > maxVisible) {
            finalHTML += `
              <div style="padding: 6px 12px; background: #f8fafc; text-align: left;">
                <button 
                  class="view-more-btn" 
                  data-row-id="${row.id}"
                  style="background: transparent; color: #003b6f; border: none; padding: 0; font-size: 12px; font-weight: 600; cursor: pointer;"
                  onmouseover="this.style.textDecoration='underline'"
                  onmouseout="this.style.textDecoration='none'"
                >
                  View all ${parsedChanges.length} changes
                </button>
              </div>
            `;
          }

          finalHTML += `</div>`;
          return finalHTML;
        }
      }
      return escapeHtml(row.description) || "-";
    },
  },
  {
    field: "ip_address",
    header: "IP Address",
    sortable: true,
    formatter: (value) => value || "-",
  },
  {
    field: "created_at",
    header: "Timestamp",
    sortable: true,
    type: "datetime",
    formatter: (value) => {
      if (!value) return "-";
      return new Date(value).toLocaleString();
    },
  },
];

// Export logs
const exportLogs = async () => {
  try {
    const result = await activityLogStore.exportActivityLogs();
    if (!result.success) return;

    const logs = result.data;
    if (!logs || logs.length === 0) return;

    const getUserName = (log) => log.user_name || log.user?.name || "Unknown";

    const headers = ["User", "Action", "Details", "IP Address", "Timestamp"];
    const csvRows = [headers.join(",")];

    logs.forEach((log) => {
      const userName = getUserName(log);
      let detailsText = log.description || "";

      if (log.action && log.action.endsWith(".updated") && log.changes) {
        let changesObj = log.changes;
        if (typeof changesObj === "string") {
          try {
            changesObj = JSON.parse(changesObj);
          } catch (e) {}
        }

        if (typeof changesObj === "object" && changesObj !== null) {
          const parsed = parseChanges(changesObj);
          if (parsed.length > 0) {
            detailsText = parsed
              .map((c) => `${c.label}: ${c.oldVal} -> ${c.newVal}`)
              .join(" | ");
          }
        }
      }

      const row = [
        `"${userName.replace(/"/g, '""')}"`,
        `"${(log.action || "").replace(/"/g, '""')}"`,
        `"${detailsText.replace(/"/g, '""')}"`,
        `"${(log.ip_address || "").replace(/"/g, '""')}"`,
        `"${log.created_at ? new Date(log.created_at).toLocaleString() : ""}"`,
      ];
      csvRows.push(row.join(","));
    });

    const csv = csvRows.join("\n");
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const link = document.createElement("a");
    const url = URL.createObjectURL(blob);

    link.setAttribute("href", url);
    link.setAttribute(
      "download",
      `activity-logs-${new Date().toISOString().split("T")[0]}.csv`,
    );
    link.style.visibility = "hidden";

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  } catch (error) {
    console.error("Export error:", error);
  }
};

const clearFilters = () => {
  activityLogStore.updateSearchParams({ page: 1, q: "", action: "" });
};

const handlePageChange = (event) => {
  const page = event.page ? event.page + 1 : 1;
  const rows = event.rows || pagination.value.per_page;
  activityLogStore.changePage(page, rows);
};

const handleSortChange = (event) => {
  console.log("Sort change:", event);
};

const handleSearch = (searchValue) => {
  activityLogStore.updateSearchParams({
    page: 1,
    q: searchValue,
    action: filterAction.value,
  });
};

const handleClearSearch = () => {
  activityLogStore.updateSearchParams({
    page: 1,
    q: "",
    action: filterAction.value,
  });
};
</script>

<style scoped>
.activity-log-page {
  padding: 1.5rem;
  min-height: 100vh;
}

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

.page-title {
  font-size: 2rem;
  font-weight: 700;
  color: #1a202c;
  margin: 0 0 0.5rem 0;
}

.page-subtitle {
  color: #64748b;
  font-size: 1rem;
  margin: 0;
}

.statistics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.25rem;
  margin-bottom: 2rem;
}

.stat-card {
  background: white;
  border-radius: 12px;
  padding: 1.5rem;
  box-shadow:
    0 1px 3px 0 rgba(0, 0, 0, 0.1),
    0 1px 2px 0 rgba(0, 0, 0, 0.06);
  transition: all 0.3s ease;
}

.stat-card:hover {
  transform: translateY(-4px);
  box-shadow:
    0 10px 15px -3px rgba(0, 0, 0, 0.1),
    0 4px 6px -2px rgba(0, 0, 0, 0.05);
}

.stat-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.stat-info {
  flex: 1;
}

.stat-label {
  font-size: 0.875rem;
  color: #64748b;
  margin: 0 0 0.5rem 0;
  font-weight: 500;
}

.stat-value {
  font-size: 1.875rem;
  font-weight: 700;
  color: #1a202c;
  margin: 0;
}

.stat-icon {
  width: 56px;
  height: 56px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
}

.stat-icon-primary {
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
}
.stat-icon-success {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
}
.stat-icon-info {
  background: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%);
}
.stat-icon-warning {
  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
}

.page-content {
  background: white;
  border-radius: 12px;
  box-shadow:
    0 1px 3px 0 rgba(0, 0, 0, 0.1),
    0 1px 2px 0 rgba(0, 0, 0, 0.06);
  overflow: hidden;
}

.toolbar {
  padding: 1.5rem;
  border-bottom: 1px solid #e2e8f0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.search-section {
  flex: 1;
  max-width: 400px;
  min-width: 250px;
}

.filter-section {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.filter-select {
  min-width: 200px;
}

:deep(.activity-log-table) {
  font-family:
    "Inter",
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    sans-serif;
}

:deep(.activity-log-table .p-datatable-thead > tr > th) {
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  font-weight: 600;
  color: #475569;
  border-bottom: 2px solid #e2e8f0;
  padding: 1rem;
}

:deep(.activity-log-table .p-datatable-tbody > tr) {
  transition: all 0.2s ease;
}

:deep(.activity-log-table .p-datatable-tbody > tr:hover) {
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  transform: translateY(-1px);
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
}

:deep(.activity-log-table .p-badge) {
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.025em;
  padding: 0.375rem 0.75rem;
}

/* ========================================= */
/* MODAL & TABLE CONTENT THEME               */
/* ========================================= */

.header-subtitle-alt {
  text-align: center;
  color: #6b7280;
  font-size: 0.95rem;
  margin-top: -0.5rem;
  margin-bottom: 1.5rem;
}

.dialog-content-grey {
  background-color: #f3f4f6;
  padding: 2rem 1.5rem;
  height: auto;
  overflow: visible;
  margin: 0;
}

/* Single Unified Container for Changes */
.changes-list-container {
  background: white;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

/* Individual Packed Row Items */
.compact-change-item {
  padding: 10px 16px;
  border-bottom: 1px solid #e2e8f0;
  background: #ffffff;
}

.compact-change-item:last-child {
  border-bottom: none;
}

/* Heading Typography */
.change-label {
  color: #003b6f;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 4px;
}

/* Values Container */
.change-values {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  font-size: 13px;
  gap: 6px;
  word-break: break-word;
}

.val-old {
  color: #ef4444;
  text-decoration: line-through;
  font-weight: 500;
}

.val-arrow {
  color: #94a3b8;
  font-weight: bold;
}

.val-new {
  color: #10b981;
  font-weight: 600;
}

@media (max-width: 768px) {
  .activity-log-page {
    padding: 1rem;
  }
  .page-header {
    flex-direction: column;
    align-items: flex-start;
  }
  .page-title {
    font-size: 1.5rem;
  }
  .statistics-grid {
    grid-template-columns: 1fr;
  }
  .toolbar {
    flex-direction: column;
    align-items: stretch;
  }
  .search-section {
    max-width: none;
  }
  .filter-section {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-select {
    width: 100%;
  }

  .dialog-content-grey {
    padding: 1.5rem 1rem;
  }
}

:deep(.p-datatable-scrollable-body)::-webkit-scrollbar {
  height: 8px;
  width: 8px;
}
:deep(.p-datatable-scrollable-body)::-webkit-scrollbar-track {
  background: #f1f5f9;
  border-radius: 4px;
}
:deep(.p-datatable-scrollable-body)::-webkit-scrollbar-thumb {
  background: #cbd5e1;
  border-radius: 4px;
}
:deep(.p-datatable-scrollable-body)::-webkit-scrollbar-thumb:hover {
  background: #94a3b8;
}
:deep(.p-datatable-loading-overlay) {
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(4px);
}
</style>
