import {
  Alert,
  Box,
  Button,
  Chip,
  IconButton,
  Paper,
  Stack,
  TextField,
  Tooltip,
  Typography
} from "@exotel-npm-dev/signal-design-system";
import { useMemo, useState, type MouseEvent } from "react";
import { safeJson } from "../utils/safeJson";

export type EventEntry = {
  id: string;
  ts: number;
  name: string;
  data: unknown;
};

function formatTs(ts: number): string {
  const d = new Date(ts);
  const hh = String(d.getHours()).padStart(2, "0");
  const mm = String(d.getMinutes()).padStart(2, "0");
  const ss = String(d.getSeconds()).padStart(2, "0");
  const ms = String(d.getMilliseconds()).padStart(3, "0");
  return `${hh}:${mm}:${ss}.${ms}`;
}

function CopyButton({ text }: { text: string }) {
  const [copied, setCopied] = useState(false);
  return (
    <Tooltip title={copied ? "Copied" : "Copy"} arrow>
      <IconButton
        size="small"
        onClick={(e: MouseEvent<HTMLButtonElement>) => {
          e.stopPropagation();
          void navigator.clipboard
            .writeText(text)
            .then(() => {
              setCopied(true);
              window.setTimeout(() => setCopied(false), 1200);
            })
            .catch(() => undefined);
        }}
        aria-label="Copy"
      >
        <Box component="span" sx={{ fontSize: 12 }}>
          {copied ? "✓" : "⧉"}
        </Box>
      </IconButton>
    </Tooltip>
  );
}

export function EventsPanel({
  events,
  onClear,
  registered
}: {
  events: EventEntry[];
  onClear: () => void;
  registered: string[];
}) {
  const [filter, setFilter] = useState("");
  const [expanded, setExpanded] = useState<Record<string, boolean>>({});

  const visible = useMemo(() => {
    const q = filter.trim().toLowerCase();
    const matched = q
      ? events.filter((e) => {
          if (e.name.toLowerCase().includes(q)) return true;
          try {
            return safeJson(e.data).toLowerCase().includes(q);
          } catch {
            return false;
          }
        })
      : events;
    // Force newest-first regardless of how the parent stored them — defensive
    // against future state changes / restored sessionStorage order.
    return [...matched].sort((a, b) => b.ts - a.ts);
  }, [events, filter]);

  return (
    <Stack spacing={1.5}>
      <Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap">
        <TextField
          size="small"
          placeholder="Search events by name or payload…"
          value={filter}
          onChange={(e) => setFilter(e.target.value)}
          sx={{ minWidth: 240, flex: 1 }}
        />
        <Button size="small" variant="outlined" color="error" onClick={onClear} disabled={events.length === 0}>
          Clear events
        </Button>
        <Box sx={{ flexBasis: "100%", height: 0 }} />
        <Typography variant="caption" color="text.secondary">
          Showing {visible.length} of {events.length}
        </Typography>
      </Stack>

      {events.length === 0 && (
        <Alert severity="info" variant="outlined">
          No events yet. Trigger something in the agent UI (start a call, change state, accept chat).
          Listeners include:{" "}
          <Box component="span" sx={{ fontFamily: "monospace", fontSize: 12 }}>
            {registered.slice(0, 8).join(", ")}
            {registered.length > 8 ? `, +${registered.length - 8} more` : ""}
          </Box>
        </Alert>
      )}

      <Stack spacing={1}>
        {visible.map((ev) => {
          const isOpen = !!expanded[ev.id];
          const payloadStr = safeJson(ev.data);
          return (
            <Paper
              key={ev.id}
              variant="outlined"
              onClick={() => setExpanded((m) => ({ ...m, [ev.id]: !isOpen }))}
              sx={{
                p: 1.25,
                cursor: "pointer",
                userSelect: "none",
                borderLeft: 3,
                borderLeftColor: "primary.main",
                "&:hover": { bgcolor: "action.hover" }
              }}
            >
              <Stack direction="row" spacing={1} alignItems="center">
                <Box
                  component="span"
                  aria-hidden
                  sx={{
                    fontSize: 10,
                    color: "text.secondary",
                    transform: isOpen ? "rotate(90deg)" : "rotate(0deg)",
                    transition: "transform 0.15s ease",
                    width: 12,
                    display: "inline-block"
                  }}
                >
                  ▶
                </Box>
                <Chip size="small" label={ev.name} color="primary" variant="outlined" />
                <Typography variant="caption" color="text.secondary">
                  {formatTs(ev.ts)}
                </Typography>
                <Box sx={{ flexGrow: 1 }} />
                <CopyButton text={payloadStr} />
              </Stack>
              {isOpen && (
                <Box
                  component="pre"
                  onClick={(e: MouseEvent<HTMLPreElement>) => e.stopPropagation()}
                  sx={{
                    mt: 1,
                    mb: 0,
                    p: 1,
                    bgcolor: "action.hover",
                    borderRadius: 1,
                    fontSize: 12,
                    overflow: "auto",
                    maxHeight: 320,
                    cursor: "text"
                  }}
                >
                  {payloadStr}
                </Box>
              )}
            </Paper>
          );
        })}
      </Stack>
    </Stack>
  );
}
