// =============================================================================
// HeadlineSift.com — Raw Article List Table
// =============================================================================
"use client";

import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useTransition } from "react";
import { hideArticle, rejectArticle } from "./actions";
import { cn } from "@/lib/utils";

// ============================================================================
// Types
// ============================================================================

export interface RawArticleRow {
  id: string;
  sourceId: string;
  sourceName: string;
  countryId: string | null;
  countryName: string | null;
  countryCode: string | null;
  categoryId: string | null;
  categoryName: string | null;
  title: string;
  originalUrl: string;
  author: string | null;
  publishedAt: Date;
  fetchedAt: Date;
  status: string;
  clustered: boolean;
  language: string;
  urlHash: string;
}

interface SelectOption {
  id: string;
  name: string;
}

interface RawArticleTableProps {
  articles: RawArticleRow[];
  searchQuery: string;
  sourceFilter: string | null;
  countryFilter: string | null;
  categoryFilter: string | null;
  statusFilter: string | null;
  startDateFilter: string | null;
  endDateFilter: string | null;
  page: number;
  totalPages: number;
  totalCount: number;
  sourceOptions: SelectOption[];
  countryOptions: SelectOption[];
  categoryOptions: SelectOption[];
}

// ============================================================================
// Sub-components
// ============================================================================

function StatusBadge({ status, clustered }: { status: string; clustered: boolean }) {
  const base = "inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider";

  switch (status) {
    case "PENDING":
      return (
        <span className={cn(base, "bg-blue-50 text-blue-700")}>
          {clustered && <span className="inline-block h-1.5 w-1.5 rounded-full bg-blue-400" title="Assigned to cluster" />}
          Pending
        </span>
      );
    case "PROCESSED":
      return (
        <span className={cn(base, "bg-green-50 text-green-700")}>
          Processed
        </span>
      );
    case "SKIPPED":
      return (
        <span className={cn(base, "bg-slate-100 text-slate-500")}>
          Hidden
        </span>
      );
    case "ERROR":
      return (
        <span className={cn(base, "bg-red-50 text-red-700")}>
          Rejected
        </span>
      );
    default:
      return (
        <span className={cn(base, "bg-slate-100 text-slate-600")}>
          {status}
        </span>
      );
  }
}

function DuplicateDot({ urlHash, allHashes }: { urlHash: string; allHashes: string[] }) {
  const count = allHashes.filter((h) => h === urlHash).length;
  if (count <= 1) return null;

  return (
    <span
      className="inline-flex h-4 w-4 items-center justify-center rounded-full bg-amber-100 text-2xs font-bold text-amber-700"
      title={`${count} articles share this URL`}
    >
      {count > 9 ? "9+" : count}
    </span>
  );
}

function RelativeDate({ date }: { date: Date }) {
  const now = Date.now();
  const diffMs = now - date.getTime();
  const diffMin = Math.floor(diffMs / 60_000);
  const diffHr = Math.floor(diffMin / 60);
  const diffDay = Math.floor(diffHr / 24);

  let text: string;
  if (diffMin < 1) text = "just now";
  else if (diffMin < 60) text = `${diffMin}m ago`;
  else if (diffHr < 24) text = `${diffHr}h ago`;
  else if (diffDay < 7) text = `${diffDay}d ago`;
  else text = date.toLocaleDateString();

  return (
    <span className="text-2xs text-body-muted" title={date.toISOString()}>
      {text}
    </span>
  );
}

function EmptyState({ hasFilters }: { hasFilters: boolean }) {
  return (
    <div className="flex flex-col items-center justify-center py-16 text-center">
      <span className="text-5xl" aria-hidden="true">
        {hasFilters ? "🔍" : "📄"}
      </span>
      <h3 className="mt-4 text-lg font-semibold text-heading">
        {hasFilters ? "No articles match your filters" : "No raw articles yet"}
      </h3>
      <p className="mt-2 max-w-md text-sm text-body-muted">
        {hasFilters
          ? "Try adjusting your search or clearing some filters."
          : "Articles appear here after sources are fetched. Run a fetch to populate this inbox."}
      </p>
    </div>
  );
}

// ============================================================================
// Table Component
// ============================================================================

export default function RawArticleTable({
  articles,
  searchQuery,
  sourceFilter,
  countryFilter,
  categoryFilter,
  statusFilter,
  startDateFilter,
  endDateFilter,
  page,
  totalPages,
  totalCount,
  sourceOptions,
  countryOptions,
  categoryOptions,
}: RawArticleTableProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [isPending, startTransition] = useTransition();

  const navigate = useCallback(
    (overrides: Record<string, string | null>) => {
      const params = new URLSearchParams(searchParams.toString());
      for (const [key, value] of Object.entries(overrides)) {
        if (value === null) {
          params.delete(key);
        } else {
          params.set(key, value);
        }
      }
      startTransition(() => {
        router.push(`/admin/raw-articles?${params.toString()}`);
      });
    },
    [router, searchParams, startTransition],
  );

  const handleHide = useCallback(
    (id: string) => {
      if (!window.confirm("Hide this article? It will be skipped during clustering.")) return;
      startTransition(() => {
        hideArticle(id);
      });
    },
    [startTransition],
  );

  const handleReject = useCallback(
    (id: string) => {
      if (!window.confirm("Reject this article? It will be marked as ERROR.")) return;
      startTransition(() => {
        rejectArticle(id);
      });
    },
    [startTransition],
  );

  const hasFilters =
    searchQuery.length > 0 ||
    sourceFilter !== null ||
    countryFilter !== null ||
    categoryFilter !== null ||
    statusFilter !== null ||
    startDateFilter !== null ||
    endDateFilter !== null;

  // Compute duplicate groups for the current page
  const allHashes = articles.map((a) => a.urlHash);

  return (
    <div className="space-y-4">
      {/* ── Filter Toolbar ── */}
      <div className="flex flex-col gap-3">
        {/* Row 1: Search */}
        <div className="relative max-w-sm">
          <svg
            className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-body-muted"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
            strokeWidth={1.5}
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"
            />
          </svg>
          <input
            type="search"
            defaultValue={searchQuery}
            placeholder="Search by title…"
            onChange={(e) => navigate({ search: e.target.value || null, page: null })}
            className="input pl-9"
          />
        </div>

        {/* Row 2: Filter dropdowns */}
        <div className="flex flex-wrap items-end gap-3">
          {/* Source */}
          <div>
            <label className="block text-2xs font-medium text-body-muted mb-1">Source</label>
            <select
              value={sourceFilter ?? ""}
              onChange={(e) => navigate({ source: e.target.value || null, page: null })}
              className="input text-xs"
              style={{ maxWidth: "11rem" }}
            >
              <option value="">All sources</option>
              {sourceOptions.map((s) => (
                <option key={s.id} value={s.id}>{s.name}</option>
              ))}
            </select>
          </div>

          {/* Country */}
          <div>
            <label className="block text-2xs font-medium text-body-muted mb-1">Country</label>
            <select
              value={countryFilter ?? ""}
              onChange={(e) => navigate({ country: e.target.value || null, page: null })}
              className="input text-xs"
              style={{ maxWidth: "9rem" }}
            >
              <option value="">All countries</option>
              {countryOptions.map((c) => (
                <option key={c.id} value={c.id}>{c.name}</option>
              ))}
            </select>
          </div>

          {/* Category */}
          <div>
            <label className="block text-2xs font-medium text-body-muted mb-1">Category</label>
            <select
              value={categoryFilter ?? ""}
              onChange={(e) => navigate({ category: e.target.value || null, page: null })}
              className="input text-xs"
              style={{ maxWidth: "9rem" }}
            >
              <option value="">All categories</option>
              {categoryOptions.map((c) => (
                <option key={c.id} value={c.id}>{c.name}</option>
              ))}
            </select>
          </div>

          {/* Status */}
          <div>
            <label className="block text-2xs font-medium text-body-muted mb-1">Status</label>
            <select
              value={statusFilter ?? ""}
              onChange={(e) => navigate({ status: e.target.value || null, page: null })}
              className="input text-xs"
              style={{ maxWidth: "7rem" }}
            >
              <option value="">All</option>
              <option value="PENDING">Pending</option>
              <option value="PROCESSED">Processed</option>
              <option value="SKIPPED">Hidden</option>
              <option value="ERROR">Rejected</option>
            </select>
          </div>

          {/* Date Range */}
          <div>
            <label className="block text-2xs font-medium text-body-muted mb-1">From</label>
            <input
              type="date"
              value={startDateFilter ?? ""}
              onChange={(e) => navigate({ startDate: e.target.value || null, page: null })}
              className="input text-xs"
              style={{ maxWidth: "9rem" }}
            />
          </div>
          <div>
            <label className="block text-2xs font-medium text-body-muted mb-1">To</label>
            <input
              type="date"
              value={endDateFilter ?? ""}
              onChange={(e) => navigate({ endDate: e.target.value || null, page: null })}
              className="input text-xs"
              style={{ maxWidth: "9rem" }}
            />
          </div>

          {hasFilters && (
            <span className="text-2xs text-body-muted self-end pb-1.5">
              {totalCount} result{totalCount !== 1 ? "s" : ""}
            </span>
          )}
        </div>
      </div>

      {/* ── Table or Empty State ── */}
      {articles.length === 0 ? (
        <div className="card">
          <EmptyState hasFilters={hasFilters} />
        </div>
      ) : (
        <div className="card overflow-x-auto p-0">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b border-border bg-surface-secondary text-left">
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted">
                  Title
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden sm:table-cell">
                  Source
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden md:table-cell">
                  Country
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden lg:table-cell">
                  Category
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden xl:table-cell">
                  Published
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted">
                  Status
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted w-24">
                  <span className="sr-only">Actions</span>
                </th>
              </tr>
            </thead>
            <tbody className="divide-y divide-border">
              {articles.map((article) => (
                <tr
                  key={article.id}
                  className={cn(
                    "transition-colors hover:bg-surface-secondary",
                    article.status === "ERROR" && "bg-red-50/30",
                  )}
                >
                  {/* Title + URL + Duplicate indicator */}
                  <td className="px-4 py-3">
                    <div className="flex items-start gap-2">
                      <DuplicateDot urlHash={article.urlHash} allHashes={allHashes} />
                      <div className="min-w-0">
                        <p className="font-medium text-heading truncate max-w-[300px]">
                          {article.title}
                        </p>
                        <a
                          href={article.originalUrl}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="text-2xs text-brand-600 hover:text-brand-700 hover:underline truncate block max-w-[300px]"
                          title={article.originalUrl}
                        >
                          {article.originalUrl}
                        </a>
                      </div>
                    </div>
                  </td>

                  {/* Source */}
                  <td className="px-4 py-3 hidden sm:table-cell">
                    <span className="text-xs text-body-muted">
                      {article.sourceName}
                    </span>
                  </td>

                  {/* Country */}
                  <td className="px-4 py-3 hidden md:table-cell">
                    {article.countryName ? (
                      <span className="text-xs text-body">
                        {article.countryName}
                      </span>
                    ) : (
                      <span className="text-body-muted/50">—</span>
                    )}
                  </td>

                  {/* Category */}
                  <td className="px-4 py-3 hidden lg:table-cell">
                    {article.categoryName ? (
                      <span className="text-xs text-body">
                        {article.categoryName}
                      </span>
                    ) : (
                      <span className="text-body-muted/50">—</span>
                    )}
                  </td>

                  {/* Published */}
                  <td className="px-4 py-3 hidden xl:table-cell">
                    <RelativeDate date={article.publishedAt} />
                  </td>

                  {/* Status */}
                  <td className="px-4 py-3">
                    <StatusBadge status={article.status} clustered={article.clustered} />
                  </td>

                  {/* Actions */}
                  <td className="px-4 py-3">
                    <div className="flex items-center gap-1">
                      {/* Hide — for PENDING articles */}
                      {article.status === "PENDING" && (
                        <button
                          type="button"
                          onClick={() => handleHide(article.id)}
                          disabled={isPending}
                          className="rounded px-2 py-1 text-2xs font-medium text-slate-500 hover:bg-slate-100 transition-colors"
                          title="Hide this article (skip during clustering)"
                        >
                          Hide
                        </button>
                      )}

                      {/* Reject — for PENDING articles */}
                      {article.status === "PENDING" && (
                        <button
                          type="button"
                          onClick={() => handleReject(article.id)}
                          disabled={isPending}
                          className="rounded px-2 py-1 text-2xs font-medium text-red-600 hover:bg-red-50 transition-colors"
                          title="Reject this article (mark as error)"
                        >
                          Reject
                        </button>
                      )}

                      {/* Open original link */}
                      <a
                        href={article.originalUrl}
                        target="_blank"
                        rel="noopener noreferrer"
                        className="rounded px-2 py-1 text-2xs font-medium text-brand-600 hover:bg-brand-50 transition-colors"
                        title="Open original article in new tab"
                      >
                        Open
                      </a>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>

          {/* Footer: count + pagination */}
          <div className="flex items-center justify-between border-t border-border px-4 py-3">
            <span className="text-xs text-body-muted">
              {totalCount} {totalCount === 1 ? "article" : "articles"}
            </span>

            {totalPages > 1 && (
              <div className="flex items-center gap-2">
                <button
                  type="button"
                  disabled={page <= 1}
                  onClick={() => navigate({ page: String(page - 1) })}
                  className="rounded px-2 py-1 text-xs text-brand-600 hover:bg-brand-50 disabled:text-body-muted/30 disabled:cursor-not-allowed transition-colors"
                >
                  Previous
                </button>
                <span className="text-xs text-body-muted">{page} / {totalPages}</span>
                <button
                  type="button"
                  disabled={page >= totalPages}
                  onClick={() => navigate({ page: String(page + 1) })}
                  className="rounded px-2 py-1 text-xs text-brand-600 hover:bg-brand-50 disabled:text-body-muted/30 disabled:cursor-not-allowed transition-colors"
                >
                  Next
                </button>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
