<script setup>
import { ref, computed } from "vue";
import Dropdown from "@/Components/Dropdown.vue";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/Components/ui/table';
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/Components/ui/select';
import { Button } from '@/Components/ui/button';
import { Badge } from '@/Components/ui/badge';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/Components/ui/dialog';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/Components/ui/accordion';

const props = defineProps({
  events: Array,
  loading: Boolean,
  limit: Number,
});
const emits = defineEmits(["update:limit", "refresh"]);
function onLimit(val) {
  emits("update:limit", Number(val));
  emits("refresh");
}

// Level filter (all | error | warning | info/other)
const levelFilter = ref("all");
const levelOptions = [
  { value: "all", label: "All" },
  { value: "error", label: "Error" },
  { value: "warning", label: "Warning" },
  { value: "info", label: "Info / Other" },
];

const filteredEvents = computed(() => {
  if (levelFilter.value === "all") return props.events || [];
  if (levelFilter.value === "info") {
    return (props.events || []).filter(
      (e) => e.level !== "error" && e.level !== "warning"
    );
  }
  return (props.events || []).filter((e) => e.level === levelFilter.value);
});

// Expanded state per event id
const expanded = ref(new Set());
function isExpanded(id) {
  return expanded.value.has(id);
}
function toggleExpand(id) {
  if (expanded.value.has(id)) {
    expanded.value.delete(id);
  } else {
    expanded.value.add(id);
  }
  expanded.value = new Set(expanded.value);
}

// Entity details dialog
const detailsDialog = ref(false);
const selectedEvent = ref(null);

function hasEntityDetails(ev) {
  const ctx = tryJson(ev.context);
  return ctx && Array.isArray(ctx.entity_details) && ctx.entity_details.length > 0;
}

function showEntityDetails(ev) {
  selectedEvent.value = ev;
  detailsDialog.value = true;
}

function getEntityDetails(ev) {
  if (!ev) return [];
  const ctx = tryJson(ev.context);
  return ctx?.entity_details || [];
}

function getRawData(ev) {
  if (!ev) return {};
  const ctx = tryJson(ev.context);
  return ctx?.raw_data || {};
}

function isLong(msg) {
  return msg && String(msg).length > 160;
}
function shortMsg(msg) {
  if (!msg) return "";
  const s = String(msg);
  return s.length <= 160 ? s : s.slice(0, 160) + "…";
}

function tryJson(val) {
  if (val == null) return null;
  if (typeof val === "object") return val;
  if (typeof val === "string") {
    const t = val.trim();
    if (
      (t.startsWith("{") && t.endsWith("}")) ||
      (t.startsWith("[") && t.endsWith("]"))
    ) {
      try {
        return JSON.parse(t);
      } catch {
        return null;
      }
    }
  }
  return null;
}

function contextPreview(ctx) {
  if (!ctx) return "";
  const obj = tryJson(ctx) || ctx;
  let str = typeof obj === "string" ? obj : JSON.stringify(obj);
  if (str.length > 60) str = str.slice(0, 60) + "…";
  return str;
}

// JSON formatting & lightweight syntax highlight
function htmlEscape(s) {
  return s
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}

function prettyJson(val) {
  const obj = tryJson(val);
  if (!obj) {
    return htmlEscape(typeof val === "string" ? val : String(val ?? ""));
  }
  try {
    return htmlEscape(JSON.stringify(obj, null, 2));
  } catch {
    return htmlEscape(String(val ?? ""));
  }
}

function highlightJson(val) {
  const src = prettyJson(val);
  return src.replace(
    /(\"([^"\\]|\\.)*\"\s*:)|(\"([^"\\]|\\.)*\")|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?/g,
    (match) => {
      if (/^\"([^"\\]|\\.)*\"\s*:/.test(match)) {
        return `<span class=\"text-indigo-600\">${match}</span>`; // key
      }
      if (/^\"/.test(match)) {
        return `<span class=\"text-emerald-700\">${match}</span>`; // string
      }
      if (/true|false/.test(match)) {
        return `<span class=\"text-orange-600 font-medium\">${match}</span>`; // boolean
      }
      if (/null/.test(match)) {
        return `<span class=\"text-gray-500 italic\">${match}</span>`; // null
      }
      if (/^-?\d/.test(match)) {
        return `<span class=\"text-fuchsia-700\">${match}</span>`; // number
      }
      return match;
    }
  );
}

function formattedContext(ctx) {
  return highlightJson(ctx);
}
</script>

<template>
  <div class="pt-4">
    <div class="flex items-center justify-between mb-2">
      <h3 class="font-semibold">Logs</h3>
      <div class="flex items-center flex-wrap gap-2 text-sm">
        <span class="text-muted-foreground">Show</span>
        <Select :model-value="limit.toString()" @update:model-value="onLimit">
          <SelectTrigger class="w-20 h-8">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectGroup>
              <SelectItem value="50">50</SelectItem>
              <SelectItem value="100">100</SelectItem>
              <SelectItem value="200">200</SelectItem>
              <SelectItem value="500">500</SelectItem>
            </SelectGroup>
          </SelectContent>
        </Select>
        <span class="text-muted-foreground ml-2">Level</span>
        <Select v-model="levelFilter">
          <SelectTrigger class="w-32 h-8">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectGroup>
              <SelectItem v-for="opt in levelOptions" :key="opt.value" :value="opt.value">
                {{ opt.label }}
              </SelectItem>
            </SelectGroup>
          </SelectContent>
        </Select>
        <Button
          variant="outline"
          size="sm"
          @click.prevent="$emit('refresh')"
          :disabled="loading"
        >
          {{ loading ? "Refreshing…" : "Refresh" }}
        </Button>
      </div>
    </div>
    <div class="overflow-x-auto max-h-[30rem] overflow-y-auto rounded-lg border">
      <Table>
        <TableHeader class="sticky top-0 z-10">
          <TableRow>
            <TableHead class="w-[160px]">Time</TableHead>
            <TableHead class="w-[80px]">Level</TableHead>
            <TableHead class="w-[160px]">Event</TableHead>
            <TableHead>Message</TableHead>
            <TableHead class="w-[64px]">Row</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          <TableRow v-for="ev in filteredEvents" :key="ev.id">
            <TableCell class="whitespace-nowrap">
              {{ new Date(ev.created_at).toLocaleString() }}
            </TableCell>
            <TableCell>
              <Badge
                :variant="ev.level === 'error' ? 'destructive' : ev.level === 'warning' ? 'default' : 'secondary'"
                :class="[
                  'text-xs',
                  ev.level === 'warning' ? 'bg-amber-100 text-amber-800 hover:bg-amber-100' : ''
                ]"
              >{{ ev.level }}</Badge>
            </TableCell>
            <TableCell class="max-w-[9rem]">
              <span class="block truncate" :title="ev.event">{{ ev.event }}</span>
            </TableCell>
            <TableCell class="max-w-[28rem]">
              <div class="space-y-1 break-words">
                <div class="leading-snug whitespace-pre-wrap">
                  <span v-if="!isLong(ev.message)">{{ ev.message }}</span>
                  <span v-else>
                    <span v-if="!isExpanded(ev.id)">{{ shortMsg(ev.message) }}</span>
                    <span v-else>{{ ev.message }}</span>
                    <button
                      type="button"
                      class="ml-2 inline-flex items-center gap-0.5 text-xs text-indigo-600 hover:underline"
                      @click="toggleExpand(ev.id)"
                    >
                      {{ isExpanded(ev.id) ? "Show less" : "Read more" }}
                    </button>
                  </span>
                </div>
                <div v-if="ev.context" class="text-xs text-gray-600 flex items-center gap-2">
                  <button
                    v-if="hasEntityDetails(ev)"
                    type="button"
                    class="px-2 py-1 rounded border border-indigo-300 bg-indigo-50 hover:bg-indigo-100 text-indigo-700 transition text-[11px] font-medium"
                    @click="showEntityDetails(ev)"
                  >
                    📋 Entity Details
                  </button>
                  <Dropdown
                    align="left"
                    width="wide"
                    :content-classes="[
                      'p-3',
                      'bg-white',
                      'text-xs',
                      'break-words',
                      'space-y-2',
                      'max-h-[28rem]',
                      'overflow-auto',
                      'max-w-[34rem]',
                    ]"
                    :close-on-content-click="false"
                  >
                    <template #trigger>
                      <button
                        type="button"
                        class="px-1.5 py-0.5 rounded border border-gray-300 bg-gray-50 hover:bg-gray-100 text-gray-700 transition text-[11px] font-medium"
                      >
                        Context: {{ contextPreview(ev.context) }}
                      </button>
                    </template>
                    <template #content>
                      <div
                        class="font-medium text-gray-700 mb-1 flex items-center justify-between"
                      >
                        <span>Context JSON</span>
                        <span class="text-[10px] text-gray-400">ID: {{ ev.id }}</span>
                      </div>
                      <pre
                        class="whitespace-pre break-words text-gray-800 text-[11px] leading-snug"
                      >
                        <code v-html="formattedContext(ev.context)"></code>
                      </pre>
                    </template>
                  </Dropdown>
                </div>
              </div>
            </TableCell>
            <TableCell>{{ ev.import_row_id ?? "—" }}</TableCell>
          </TableRow>
          <TableRow v-if="!filteredEvents.length">
            <TableCell colspan="5" class="text-center text-muted-foreground">No events yet</TableCell>
          </TableRow>
        </TableBody>
      </Table>
    </div>
    
    <!-- Entity Details Dialog -->
    <Dialog v-model:open="detailsDialog">
      <DialogContent class="max-w-2xl max-h-[80vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Entity Processing Details</DialogTitle>
          <DialogDescription v-if="selectedEvent">
            Row {{ tryJson(selectedEvent.context)?.row || '—' }} - {{ selectedEvent.event }}
          </DialogDescription>
        </DialogHeader>
        <div v-if="selectedEvent" class="space-y-3 mt-4">
          <div 
            v-for="(detail, idx) in getEntityDetails(selectedEvent)" 
            :key="idx"
            class="p-3 rounded-lg border"
            :class="{
              'bg-red-50 border-red-200': detail.level === 'error',
              'bg-amber-50 border-amber-200': detail.level === 'warning',
              'bg-green-50 border-green-200': detail.level === 'info' && detail.action === 'inserted',
              'bg-blue-50 border-blue-200': detail.level === 'info' && detail.action === 'updated',
              'bg-gray-50 border-gray-200': detail.level === 'info' && detail.action === 'skipped'
            }"
          >
            <div class="flex items-start justify-between mb-2">
              <div class="font-medium text-sm capitalize">{{ detail.entity }}</div>
              <Badge 
                :variant="detail.level === 'error' ? 'destructive' : detail.level === 'warning' ? 'default' : 'secondary'"
                :class="[
                  'text-xs',
                  detail.level === 'warning' ? 'bg-amber-100 text-amber-800 hover:bg-amber-100' : '',
                  detail.action === 'inserted' ? 'bg-green-100 text-green-800 hover:bg-green-100' : '',
                  detail.action === 'updated' ? 'bg-blue-100 text-blue-800 hover:bg-blue-100' : '',
                  detail.action === 'skipped' ? 'bg-gray-200 text-gray-700 hover:bg-gray-200' : ''
                ]"
              >
                {{ detail.action }}{{ detail.count > 1 ? ` (${detail.count})` : '' }}
              </Badge>
            </div>
            <div v-if="detail.message" class="text-sm text-gray-700 mb-1">
              {{ detail.message }}
            </div>
            <div v-if="detail.errors && detail.errors.length" class="mt-2 space-y-1">
              <div class="text-xs font-medium text-red-700">Errors:</div>
              <div 
                v-for="(err, errIdx) in detail.errors" 
                :key="errIdx"
                class="text-xs text-red-600 pl-3"
              >
                • {{ err }}
              </div>
            </div>
            <div v-if="detail.exception" class="mt-2 p-2 bg-red-100 rounded border border-red-200">
              <div class="text-xs font-semibold text-red-800 mb-1">Exception:</div>
              <div class="text-xs text-red-700">{{ detail.exception.message }}</div>
              <div v-if="detail.exception.file" class="text-xs text-red-600 mt-1">
                {{ detail.exception.file }}:{{ detail.exception.line }}
              </div>
            </div>
          </div>
          <div v-if="getEntityDetails(selectedEvent).length === 0" class="text-center text-muted-foreground py-4">
            No entity details available
          </div>
          
          <!-- Raw Row Data Accordion -->
          <Accordion type="single" collapsible class="mt-4 border-t pt-4">
            <AccordionItem value="raw-data" class="border-b-0">
              <AccordionTrigger class="text-sm font-medium hover:no-underline py-2">
                📄 Raw Row Data (JSON)
              </AccordionTrigger>
              <AccordionContent>
                <pre class="text-xs bg-gray-900 text-gray-100 p-3 rounded overflow-x-auto mt-2">{{ JSON.stringify(getRawData(selectedEvent), null, 2) }}</pre>
              </AccordionContent>
            </AccordionItem>
          </Accordion>
        </div>
      </DialogContent>
    </Dialog>
  </div>
</template>
