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

import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
import { useCallback, useTransition } from "react";
import { toggleSourceStatus, deleteSource, fetchSourceNow } from "./actions";
import { cn } from "@/lib/utils";

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

export interface SourceRow {
  id: string;
  name: string;
  websiteUrl: string;
  sourceType: string;
  feedUrl: string | null;
  apiUrl: string | null;
  language: string;
  trustScore: number; // 1-10 display scale
  reliabilityScore: number;
  duplicateRate: number;
  clickbaitRate: number;
  isOfficial: boolean;
  status: string;
  fetchFrequencyMinutes: number;
  lastFetchedAt: Date | null;
  lastFetchStatus: string | null;
  consecutiveFailures: number;
  lastErrorMessage: string | null;
  usageNotes: string | null;
  createdAt: Date;
  /** Computed health: healthy | warning | error | unknown */
  health: "healthy" | "warning" | "error" | "unknown";
  /** Count of dependent records (for delete gating). */
  dependentCount: number;
}

interface SourceTableProps {
  sources: SourceRow[];
  searchQuery: string;
  typeFilter: string | null;
  statusFilter: string | null;
  languageFilter: string | null;
  isOfficialFilter: string | null;
  languages: string[];
  editingId: string | null;
  onEdit: (id: string) => void;
  onAdd: () => void;
}

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

function StatusBadge({ status }: { status: string }) {
  switch (status) {
    case "ACTIVE":
      return (
        <span className="inline-flex items-center rounded-full bg-green-50 px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider text-green-700">
          Active
        </span>
      );
    case "INACTIVE":
      return (
        <span className="inline-flex items-center rounded-full bg-slate-100 px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider text-slate-600">
          Inactive
        </span>
      );
    case "ERROR":
      return (
        <span className="inline-flex items-center rounded-full bg-red-50 px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider text-red-700">
          Error
        </span>
      );
    case "RATE_LIMITED":
      return (
        <span className="inline-flex items-center rounded-full bg-amber-50 px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider text-amber-700">
          Rate Limited
        </span>
      );
    default:
      return (
        <span className="inline-flex items-center rounded-full bg-slate-100 px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider text-slate-600">
          {status}
        </span>
      );
  }
}

function TypeBadge({ type }: { type: string }) {
  const colors: Record<string, string> = {
    RSS: "bg-blue-50 text-blue-700",
    API: "bg-purple-50 text-purple-700",
    MANUAL: "bg-slate-100 text-slate-600",
    SCRAPE: "bg-amber-50 text-amber-700",
  };

  return (
    <span
      className={cn(
        "inline-flex items-center rounded-full px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider",
        colors[type] ?? "bg-slate-100 text-slate-600",
      )}
    >
      {type}
    </span>
  );
}

function TrustBadge({ score }: { score: number }) {
  // score is 1-10 display scale
  let color: string;
  if (score >= 7) color = "bg-green-50 text-green-700";
  else if (score >= 4) color = "bg-amber-50 text-amber-700";
  else color = "bg-red-50 text-red-700";

  return (
    <span
      className={cn(
        "inline-flex items-center rounded-full px-2 py-0.5 text-2xs font-semibold tabular-nums",
        color,
      )}
      title={`Trust score: ${score}/10`}
    >
      {score}/10
    </span>
  );
}

function HealthDot({ health }: { health: SourceRow["health"] }) {
  const colors: Record<SourceRow["health"], string> = {
    healthy: "bg-green-500",
    warning: "bg-amber-500",
    error: "bg-red-500",
    unknown: "bg-slate-300",
  };

  const labels: Record<SourceRow["health"], string> = {
    healthy: "Healthy — last fetch succeeded",
    warning: "Warning — recent issues detected",
    error: "Error — consecutive failures",
    unknown: "Unknown — never fetched",
  };

  return (
    <span
      className={cn("inline-block h-2.5 w-2.5 rounded-full", colors[health])}
      title={labels[health]}
      aria-label={labels[health]}
    />
  );
}

function LastFetchCell({
  status,
  lastFetchedAt,
}: {
  status: string | null;
  lastFetchedAt: Date | null;
}) {
  if (!lastFetchedAt && !status) {
    return <span className="text-2xs text-body-muted">Never</span>;
  }

  const timeAgo = lastFetchedAt ? relativeTime(lastFetchedAt) : null;

  let statusLabel: string;
  let statusColor: string;
  switch (status) {
    case "SUCCESS":
      statusLabel = "OK";
      statusColor = "text-green-600";
      break;
    case "PARTIAL":
      statusLabel = "Partial";
      statusColor = "text-amber-600";
      break;
    case "FAILED":
      statusLabel = "Failed";
      statusColor = "text-red-600";
      break;
    default:
      statusLabel = status ?? "—";
      statusColor = "text-body-muted";
  }

  return (
    <div className="flex flex-col gap-0.5">
      <span className={cn("text-2xs font-medium", statusColor)}>
        {statusLabel}
      </span>
      {timeAgo && (
        <span className="text-2xs text-body-muted">{timeAgo}</span>
      )}
    </div>
  );
}

/** Quick-and-dirty relative time formatter (avoids pulling in date-fns for one use). */
function relativeTime(date: Date): string {
  const now = Date.now();
  const diffMs = now - date.getTime();
  const diffSec = Math.floor(diffMs / 1000);
  const diffMin = Math.floor(diffSec / 60);
  const diffHr = Math.floor(diffMin / 60);
  const diffDay = Math.floor(diffHr / 24);

  if (diffSec < 60) return "just now";
  if (diffMin < 60) return `${diffMin}m ago`;
  if (diffHr < 24) return `${diffHr}h ago`;
  if (diffDay < 30) return `${diffDay}d ago`;
  return date.toLocaleDateString();
}

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 sources match your filters" : "No sources yet"}
      </h3>
      <p className="mt-2 max-w-md text-sm text-body-muted">
        {hasFilters
          ? "Try adjusting your search query or clear the filters."
          : "Add your first news source to start aggregating content."}
      </p>
    </div>
  );
}

function DeleteButton({ source }: { source: SourceRow }) {
  const [isPending, startTransition] = useTransition();

  const handleDelete = useCallback(() => {
    if (source.dependentCount > 0) {
      alert(
        `Cannot delete "${source.name}" — it has ${source.dependentCount} dependent record(s). Remove or reassign those records first.`,
      );
      return;
    }
    const confirmed = window.confirm(
      `Delete "${source.name}"?\n\nThis action cannot be undone.`,
    );
    if (!confirmed) {
      return;
    }
    startTransition(() => {
      deleteSource(source.id);
    });
  }, [source, startTransition]);

  return (
    <button
      type="button"
      onClick={handleDelete}
      disabled={isPending}
      className={cn(
        "rounded px-2 py-1 text-2xs font-medium transition-colors",
        source.dependentCount > 0
          ? "cursor-not-allowed text-body-muted/40"
          : "text-red-600 hover:bg-red-50",
      )}
      title={
        source.dependentCount > 0
          ? `${source.dependentCount} dependent record(s) — cannot delete`
          : "Delete source"
      }
    >
      {isPending ? "Deleting…" : "Delete"}
    </button>
  );
}

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

export default function SourceTable({
  sources,
  searchQuery,
  typeFilter,
  statusFilter,
  languageFilter,
  isOfficialFilter,
  languages,
  editingId,
  onEdit,
  onAdd,
}: SourceTableProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [isPending, startTransition] = useTransition();

  // Build URL with filter changes
  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);
        }
      }
      // Remove edit param when filters change
      params.delete("edit");
      startTransition(() => {
        router.push(`/admin/sources?${params.toString()}`);
      });
    },
    [router, searchParams, startTransition],
  );

  // Search handler
  const handleSearch = useCallback(
    (value: string) => {
      navigate({ search: value || null });
    },
    [navigate],
  );

  // Filter handlers
  const handleTypeFilter = useCallback(
    (value: string) => {
      navigate({ type: value || null });
    },
    [navigate],
  );

  const handleStatusFilter = useCallback(
    (value: string) => {
      navigate({ status: value || null });
    },
    [navigate],
  );

  const handleLanguageFilter = useCallback(
    (value: string) => {
      navigate({ language: value || null });
    },
    [navigate],
  );

  const handleOfficialFilter = useCallback(
    (value: string) => {
      navigate({ isOfficial: value || null });
    },
    [navigate],
  );

  // Toggle status
  const handleToggleStatus = useCallback(
    (id: string) => {
      startTransition(() => {
        toggleSourceStatus(id);
      });
    },
    [startTransition],
  );

  // Fetch now
  const handleFetchNow = useCallback(
    (id: string) => {
      startTransition(() => {
        fetchSourceNow(id);
      });
    },
    [startTransition],
  );

  const hasFilters =
    searchQuery.length > 0 ||
    typeFilter !== null ||
    statusFilter !== null ||
    languageFilter !== null ||
    isOfficialFilter !== null;

  return (
    <div className="space-y-4">
      {/* ── Filter Toolbar ── */}
      <div className="flex flex-col gap-3">
        {/* Row 1: Search + Add */}
        <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          {/* Search */}
          <div className="relative flex-1 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 name or URL…"
              onChange={(e) => handleSearch(e.target.value)}
              className="input pl-9"
            />
          </div>

          {/* Add Button */}
          <button type="button" onClick={onAdd} className="btn-primary shrink-0">
            <svg
              className="h-4 w-4"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
              strokeWidth={2}
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                d="M12 4.5v15m7.5-7.5h-15"
              />
            </svg>
            Add Source
          </button>
        </div>

        {/* Row 2: Filters */}
        <div className="flex flex-wrap items-center gap-3">
          {/* Type Filter */}
          <select
            value={typeFilter ?? ""}
            onChange={(e) => handleTypeFilter(e.target.value)}
            className="input text-xs"
            style={{ maxWidth: "8rem" }}
          >
            <option value="">All types</option>
            <option value="RSS">RSS</option>
            <option value="API">API</option>
            <option value="MANUAL">Manual</option>
            <option value="SCRAPE">Scrape</option>
          </select>

          {/* Status Filter */}
          <select
            value={statusFilter ?? ""}
            onChange={(e) => handleStatusFilter(e.target.value)}
            className="input text-xs"
            style={{ maxWidth: "8rem" }}
          >
            <option value="">All statuses</option>
            <option value="ACTIVE">Active</option>
            <option value="INACTIVE">Inactive</option>
            <option value="ERROR">Error</option>
            <option value="RATE_LIMITED">Rate Limited</option>
          </select>

          {/* Language Filter */}
          <select
            value={languageFilter ?? ""}
            onChange={(e) => handleLanguageFilter(e.target.value)}
            className="input text-xs"
            style={{ maxWidth: "6rem" }}
          >
            <option value="">All languages</option>
            {languages.map((lang) => (
              <option key={lang} value={lang}>
                {lang}
              </option>
            ))}
          </select>

          {/* Official Filter */}
          <select
            value={isOfficialFilter ?? ""}
            onChange={(e) => handleOfficialFilter(e.target.value)}
            className="input text-xs"
            style={{ maxWidth: "8rem" }}
          >
            <option value="">All sources</option>
            <option value="true">Official only</option>
            <option value="false">Unofficial only</option>
          </select>

          {/* Active filter indicator */}
          {hasFilters && (
            <span className="text-2xs text-body-muted">
              {sources.length} result{sources.length !== 1 ? "s" : ""}
            </span>
          )}
        </div>
      </div>

      {/* ── Table or Empty State ── */}
      {sources.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">
                  Name
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden sm:table-cell">
                  Type
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden md:table-cell">
                  Lang
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden lg:table-cell">
                  Trust
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted w-12">
                  <span className="sr-only">Health</span>
                </th>
                <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden xl:table-cell">
                  Last Fetch
                </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-28">
                  <span className="sr-only">Actions</span>
                </th>
              </tr>
            </thead>
            <tbody className="divide-y divide-border">
              {sources.map((source) => {
                const isEditing = editingId === source.id;
                return (
                  <tr
                    key={source.id}
                    className={cn(
                      "transition-colors hover:bg-surface-secondary",
                      isEditing && "bg-brand-50/50",
                    )}
                  >
                    {/* Name + Official badge */}
                    <td className="px-4 py-3">
                      <div className="flex items-center gap-2">
                        <span className="font-medium text-heading truncate max-w-[200px]">
                          {source.name}
                        </span>
                        {source.isOfficial && (
                          <span
                            className="shrink-0 text-sm"
                            title="Official government/institutional source"
                            aria-label="Official source"
                          >
                            🏛️
                          </span>
                        )}
                      </div>
                      <p className="text-2xs text-body-muted truncate max-w-[200px] mt-0.5">
                        {source.websiteUrl}
                      </p>
                    </td>

                    {/* Type */}
                    <td className="px-4 py-3 hidden sm:table-cell">
                      <TypeBadge type={source.sourceType} />
                    </td>

                    {/* Language */}
                    <td className="px-4 py-3 hidden md:table-cell">
                      <code className="rounded bg-surface-tertiary px-1.5 py-0.5 text-xs font-mono text-body-muted">
                        {source.language}
                      </code>
                    </td>

                    {/* Trust Score */}
                    <td className="px-4 py-3 hidden lg:table-cell">
                      <TrustBadge score={source.trustScore} />
                    </td>

                    {/* Health Dot */}
                    <td className="px-4 py-3">
                      <HealthDot health={source.health} />
                    </td>

                    {/* Last Fetch */}
                    <td className="px-4 py-3 hidden xl:table-cell">
                      <LastFetchCell
                        status={source.lastFetchStatus}
                        lastFetchedAt={source.lastFetchedAt}
                      />
                    </td>

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

                    {/* Actions */}
                    <td className="px-4 py-3">
                      <div className="flex items-center gap-1">
                        {/* Edit */}
                        <button
                          type="button"
                          onClick={() => onEdit(source.id)}
                          className="rounded px-2 py-1 text-2xs font-medium text-brand-600 hover:bg-brand-50 transition-colors"
                        >
                          Edit
                        </button>

                        {/* Toggle Status (only ACTIVE ↔ INACTIVE) */}
                        {(source.status === "ACTIVE" ||
                          source.status === "INACTIVE") && (
                          <button
                            type="button"
                            onClick={() => handleToggleStatus(source.id)}
                            disabled={isPending}
                            className={cn(
                              "rounded px-2 py-1 text-2xs font-medium transition-colors",
                              source.status === "ACTIVE"
                                ? "text-amber-600 hover:bg-amber-50"
                                : "text-green-600 hover:bg-green-50",
                            )}
                          >
                            {source.status === "ACTIVE"
                              ? "Deactivate"
                              : "Activate"}
                          </button>
                        )}

                        {/* Fetch Now (RSS sources with feedUrl) */}
                        {source.sourceType === "RSS" &&
                          source.feedUrl &&
                          source.status === "ACTIVE" && (
                            <button
                              type="button"
                              onClick={() => handleFetchNow(source.id)}
                              disabled={isPending}
                              className="rounded px-2 py-1 text-2xs font-medium text-brand-600 hover:bg-brand-50 transition-colors"
                              title={`Fetch articles from "${source.name}" now`}
                            >
                              Fetch
                            </button>
                          )}

                        {/* Logs */}
                        <Link
                          href={`/admin/fetch-logs?source=${source.id}`}
                          className="rounded px-2 py-1 text-2xs font-medium text-body-muted hover:text-brand-600 hover:bg-brand-50 transition-colors"
                          title={`View fetch logs for "${source.name}"`}
                        >
                          Logs
                        </Link>

                        {/* Delete */}
                        <DeleteButton source={source} />
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>

          {/* Footer: count */}
          <div className="border-t border-border px-4 py-3 text-xs text-body-muted">
            {sources.length} {sources.length === 1 ? "source" : "sources"}
            {searchQuery.length > 0 && (
              <>
                {" "}
                matching &ldquo;{searchQuery}&rdquo;
              </>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
