"use client";

import { useEffect, useId, useRef, type ReactNode } from "react";

import { Icon, type IconName } from "./icons";
import type { Mention, ScreenState, Tone } from "./mock-data";
import { formatSouthAfricanDate } from "./workspace-access";

export function StatusLabel({
  label,
  tone = "neutral"
}: {
  readonly label: string;
  readonly tone?: Tone;
}) {
  const icon: IconName =
    tone === "urgent" || tone === "warning"
      ? "warning"
      : tone === "positive"
        ? "check"
        : tone === "ai"
          ? "sparkles"
          : "document";
  return (
    <span className={`status-label status-${tone}`}>
      <Icon name={icon} size={13} />
      {label}
    </span>
  );
}

export function SectionHeading({
  eyebrow,
  title,
  description,
  actions
}: {
  readonly eyebrow?: string;
  readonly title: string;
  readonly description?: string;
  readonly actions?: ReactNode;
}) {
  return (
    <header className="section-heading">
      <div>
        {eyebrow && <span className="section-eyebrow">{eyebrow}</span>}
        <h2>{title}</h2>
        {description && <p>{description}</p>}
      </div>
      {actions && <div className="heading-actions">{actions}</div>}
    </header>
  );
}

export function IconButton({
  icon,
  label,
  onClick,
  badge
}: {
  readonly icon: IconName;
  readonly label: string;
  readonly onClick?: () => void;
  readonly badge?: string;
}) {
  return (
    <button className="icon-button" type="button" aria-label={label} onClick={onClick}>
      <Icon name={icon} />
      {badge && <span className="icon-badge">{badge}</span>}
    </button>
  );
}

export function MiniChart({
  values,
  label,
  tone = "neutral",
  height = 52
}: {
  readonly values: readonly number[];
  readonly label: string;
  readonly tone?: Tone;
  readonly height?: number;
}) {
  const maximum = Math.max(...values);
  const minimum = Math.min(...values);
  const range = Math.max(maximum - minimum, 1);
  const points = values
    .map((value, index) => {
      const x = (index / Math.max(values.length - 1, 1)) * 100;
      const y = height - 6 - ((value - minimum) / range) * (height - 14);
      return `${x},${y}`;
    })
    .join(" ");
  return (
    <svg
      className={`mini-chart chart-${tone}`}
      height={height}
      role="img"
      viewBox={`0 0 100 ${height}`}
      preserveAspectRatio="none"
      aria-label={label}
    >
      <polyline points={points} vectorEffect="non-scaling-stroke" />
    </svg>
  );
}

export function MetricCard({
  label,
  value,
  change,
  context,
  tone,
  trend
}: {
  readonly label: string;
  readonly value: string;
  readonly change: string;
  readonly context: string;
  readonly tone: Tone;
  readonly trend: readonly number[];
}) {
  return (
    <article className="metric-card">
      <div className="metric-card-top">
        <span>{label}</span>
        <StatusLabel label={change} tone={tone} />
      </div>
      <strong>{value}</strong>
      <MiniChart values={trend} label={`${label} seven-day trend`} tone={tone} />
      <small>{context}</small>
    </article>
  );
}

export interface TableColumn {
  readonly key: string;
  readonly label: string;
  readonly align?: "left" | "right";
}

export interface TableRow {
  readonly id: string;
  readonly cells: Readonly<Record<string, ReactNode>>;
}

export function DataTable({
  caption,
  columns,
  rows
}: {
  readonly caption: string;
  readonly columns: readonly TableColumn[];
  readonly rows: readonly TableRow[];
}) {
  return (
    <div className="table-wrap" tabIndex={0} role="region" aria-label={`${caption} table`}>
      <table>
        <caption className="visually-hidden">{caption}</caption>
        <thead>
          <tr>
            {columns.map((column) => (
              <th
                key={column.key}
                scope="col"
                className={column.align === "right" ? "align-right" : undefined}
              >
                {column.label}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => (
            <tr key={row.id}>
              {columns.map((column) => (
                <td
                  key={column.key}
                  className={column.align === "right" ? "align-right" : undefined}
                >
                  {row.cells[column.key]}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export function FilterBar({
  searchLabel,
  children,
  onSearch
}: {
  readonly searchLabel: string;
  readonly children?: ReactNode;
  readonly onSearch?: (value: string) => void;
}) {
  return (
    <div className="filter-bar" role="search">
      <label className="search-control">
        <span className="visually-hidden">{searchLabel}</span>
        <Icon name="search" size={18} />
        <input
          type="search"
          placeholder={searchLabel}
          onChange={(event) => onSearch?.(event.target.value)}
        />
      </label>
      {children}
      <button className="button-secondary button-compact" type="button">
        <Icon name="filter" size={16} />
        More filters
      </button>
    </div>
  );
}

export function MentionCard({
  mention,
  onOpen
}: {
  readonly mention: Mention;
  readonly onOpen: (mention: Mention) => void;
}) {
  return (
    <article className="mention-card">
      <div className="mention-source">
        <span className="source-mark">{mention.source.slice(0, 2).toUpperCase()}</span>
        <div>
          <strong>{mention.source}</strong>
          <span>
            {mention.sourceType} · {formatSouthAfricanDate(mention.publishedAt)}
          </span>
        </div>
        <StatusLabel
          label={mention.risk === "Low" ? mention.sentiment : `${mention.risk} risk`}
          tone={
            mention.risk === "Urgent"
              ? "urgent"
              : mention.risk === "High"
                ? "warning"
                : mention.sentiment === "Positive"
                  ? "positive"
                  : "neutral"
          }
        />
      </div>
      <h3>{mention.title}</h3>
      <p>{mention.excerpt}</p>
      <div className="mention-meta">
        <span>{mention.location}</span>
        <span>{mention.reach}</span>
      </div>
      <div className="mention-footer">
        <div className="tag-list" aria-label="Mention tags">
          {mention.tags.map((tag) => (
            <span key={tag}>{tag}</span>
          ))}
        </div>
        <button className="button-text" type="button" onClick={() => onOpen(mention)}>
          View evidence <Icon name="chevron" size={16} />
        </button>
      </div>
    </article>
  );
}

export function Timeline({
  items
}: {
  readonly items: ReadonlyArray<{
    readonly time: string;
    readonly title: string;
    readonly detail: string;
    readonly tone?: Tone;
  }>;
}) {
  return (
    <ol className="timeline">
      {items.map((item) => (
        <li key={`${item.time}-${item.title}`}>
          <span className={`timeline-marker marker-${item.tone ?? "neutral"}`} />
          <time>{item.time}</time>
          <div>
            <strong>{item.title}</strong>
            <p>{item.detail}</p>
          </div>
        </li>
      ))}
    </ol>
  );
}

export function EmptyState({
  title,
  description,
  actionLabel = "Clear filters"
}: {
  readonly title: string;
  readonly description: string;
  readonly actionLabel?: string;
}) {
  return (
    <div className="empty-state">
      <span className="empty-icon">
        <Icon name="search" size={28} />
      </span>
      <h3>{title}</h3>
      <p>{description}</p>
      <button className="button-secondary" type="button">
        {actionLabel}
      </button>
    </div>
  );
}

export function ContentState({
  state,
  children,
  subject
}: {
  readonly state: ScreenState;
  readonly children: ReactNode;
  readonly subject: string;
}) {
  if (state === "loading") {
    return (
      <div className="loading-grid" aria-live="polite" aria-busy="true">
        <span className="visually-hidden">Loading {subject}</span>
        {[1, 2, 3, 4, 5, 6].map((item) => (
          <div className="skeleton-card" key={item}>
            <span />
            <span />
            <span />
          </div>
        ))}
      </div>
    );
  }
  if (state === "empty") {
    return (
      <EmptyState
        title={`No ${subject} found`}
        description="Try broadening the period or removing one or more filters."
      />
    );
  }
  if (state === "error") {
    return (
      <div className="error-state" role="alert">
        <span>
          <Icon name="warning" size={24} />
        </span>
        <div>
          <h3>We could not load {subject}</h3>
          <p>Your filters are safe. Check the mock connector and try again.</p>
        </div>
        <button className="button-secondary" type="button">
          Try again
        </button>
      </div>
    );
  }
  return children;
}

export function Drawer({
  open,
  title,
  onClose,
  children
}: {
  readonly open: boolean;
  readonly title: string;
  readonly onClose: () => void;
  readonly children: ReactNode;
}) {
  const closeButton = useRef<HTMLButtonElement>(null);
  useEffect(() => {
    if (open) closeButton.current?.focus();
  }, [open]);
  useEffect(() => {
    if (!open) return;
    const handler = (event: KeyboardEvent) => {
      if (event.key === "Escape") onClose();
    };
    document.addEventListener("keydown", handler);
    return () => document.removeEventListener("keydown", handler);
  }, [onClose, open]);
  return (
    <>
      {open && (
        <button className="drawer-scrim" aria-label="Close evidence drawer" onClick={onClose} />
      )}
      <aside
        aria-hidden={!open}
        aria-label={title}
        className={`evidence-drawer ${open ? "drawer-open" : ""}`}
      >
        <header>
          <div>
            <span className="section-eyebrow">Source evidence</span>
            <h2>{title}</h2>
          </div>
          <button
            ref={closeButton}
            className="icon-button"
            type="button"
            aria-label="Close evidence drawer"
            onClick={onClose}
          >
            <Icon name="close" />
          </button>
        </header>
        <div className="drawer-body">{children}</div>
      </aside>
    </>
  );
}

export function Modal({
  open,
  title,
  description,
  onClose,
  children
}: {
  readonly open: boolean;
  readonly title: string;
  readonly description?: string;
  readonly onClose: () => void;
  readonly children: ReactNode;
}) {
  const titleId = useId();
  const dialog = useRef<HTMLDialogElement>(null);
  useEffect(() => {
    if (open && !dialog.current?.open) dialog.current?.showModal();
    if (!open && dialog.current?.open) dialog.current.close();
  }, [open]);
  return (
    <dialog
      ref={dialog}
      aria-labelledby={titleId}
      className="modal"
      onCancel={(event) => {
        event.preventDefault();
        onClose();
      }}
      onClose={onClose}
    >
      <header>
        <div>
          <span className="section-eyebrow">New operational action</span>
          <h2 id={titleId}>{title}</h2>
          {description && <p>{description}</p>}
        </div>
        <button className="icon-button" type="button" aria-label="Close dialog" onClick={onClose}>
          <Icon name="close" />
        </button>
      </header>
      {children}
    </dialog>
  );
}
