"use client";

import { useState } from "react";

import {
  type ColumnDef,
  type Table as TableType,
  getCoreRowModel,
  useReactTable,
} from "@tanstack/react-table";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  AlertCircle,
  Archive,
  CheckCircle2,
  CircleDot,
  Eye,
  GitBranch,
  GitCommitHorizontal,
  GitFork,
  KeyRound,
  Loader2,
  RefreshCw,
  ShieldCheck,
} from "lucide-react";
import { DataTable } from "@/components/tables/DataTable";
import { cn } from "@/lib/utils";

import type {
  ForgejoRepository,
  ForgejoRepositoryValidationResponse,
} from "@/lib/api-forgejo";

const repositoryLabel = (repo: ForgejoRepository) =>
  repo.display_name || `${repo.owner}/${repo.repo}`;

const repositoryTone = (repo: ForgejoRepository) => {
  if (repo.last_sync_error) return "danger";
  if (!repo.active || repo.is_archived) return "muted";
  if (!repo.has_webhook_secret || !repo.last_sync_at) return "warning";
  return "success";
};

const toneClasses = {
  success: {
    rail: "border-l-[color:var(--success)]",
    row: "bg-[color:rgba(52,211,153,0.025)] hover:bg-[color:rgba(52,211,153,0.07)]",
    icon: "border-[color:rgba(52,211,153,0.28)] bg-[color:rgba(52,211,153,0.13)] text-[color:var(--success)]",
    dot: "bg-[color:var(--success)]",
  },
  warning: {
    rail: "border-l-[color:var(--warning)]",
    row: "bg-[color:rgba(251,191,36,0.025)] hover:bg-[color:rgba(251,191,36,0.075)]",
    icon: "border-[color:rgba(251,191,36,0.3)] bg-[color:rgba(251,191,36,0.13)] text-[color:var(--warning)]",
    dot: "bg-[color:var(--warning)]",
  },
  danger: {
    rail: "border-l-[color:var(--danger)]",
    row: "bg-[color:rgba(248,113,113,0.028)] hover:bg-[color:rgba(248,113,113,0.08)]",
    icon: "border-[color:rgba(248,113,113,0.3)] bg-[color:rgba(248,113,113,0.13)] text-[color:var(--danger)]",
    dot: "bg-[color:var(--danger)]",
  },
  muted: {
    rail: "border-l-[color:var(--border-strong)]",
    row: "hover:bg-[color:var(--surface-muted)]",
    icon: "border-[color:var(--border)] bg-[color:var(--surface-muted)] text-muted",
    dot: "bg-[color:var(--text-quiet)]",
  },
} as const;

const formatSyncTime = (value: string | null) => {
  if (!value) return null;
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return null;
  return {
    date: date.toLocaleDateString(),
    time: date.toLocaleTimeString([], {
      hour: "2-digit",
      minute: "2-digit",
    }),
  };
};

type RepositorySyncResult = {
  created: number;
  updated: number;
  open: number;
  closed: number;
  total: number;
};

interface RepositoriesTableProps {
  repositories: ForgejoRepository[];
  isLoading: boolean;
  onEdit?: (repository: ForgejoRepository) => void;
  onDelete?: (repository: ForgejoRepository) => void;
  onViewDetails?: (repository: ForgejoRepository) => void;
  onSync?: (repository: ForgejoRepository) => Promise<RepositorySyncResult>;
  onValidate?: (
    repository: ForgejoRepository,
  ) => Promise<ForgejoRepositoryValidationResponse>;
}

export function ForgejoRepositoriesTable({
  repositories,
  isLoading,
  onEdit,
  onDelete,
  onViewDetails,
  onSync,
  onValidate,
}: RepositoriesTableProps) {
  // onEdit available for future use
  const _ = onEdit;
  const table = useReactTable({
    data: repositories,
    columns: columns(onSync, onValidate, onViewDetails),
    getCoreRowModel: getCoreRowModel(),
  });

  return (
    <DataTable
      table={table}
      isLoading={isLoading}
      emptyState={{
        icon: <GitBranch className="h-12 w-12" />,
        title: "No Git Project repositories yet",
        description:
          "Add repositories so Pipeline can sync issues into Git Projects.",
        actionHref: "/git-projects/repositories/new",
        actionLabel: "Add repository",
      }}
      rowActions={{
        getEditHref: (row) => `/git-projects/repositories/${row.id}/edit`,
        onDelete: onDelete ?? undefined,
        cellClassName: "px-3 py-3 align-middle md:px-5",
      }}
      tableClassName="min-w-[900px] w-full text-left text-sm"
      headerClassName="bg-[linear-gradient(90deg,rgba(96,165,250,0.16),rgba(52,211,153,0.1),rgba(251,191,36,0.08))] text-xs font-semibold uppercase tracking-wider text-[color:var(--text-muted)]"
      headerCellClassName="px-3 py-3 md:px-5"
      cellClassName="px-3 py-4 align-middle md:px-5"
      rowClassName={(row) => {
        const tone = repositoryTone(row.original);
        return cn(
          "border-l-4 transition-colors",
          toneClasses[tone].rail,
          toneClasses[tone].row,
        );
      }}
    />
  );
}

const columns = (
  onSync?: (repository: ForgejoRepository) => Promise<RepositorySyncResult>,
  onValidate?: (
    repository: ForgejoRepository,
  ) => Promise<ForgejoRepositoryValidationResponse>,
  onViewDetails?: (repository: ForgejoRepository) => void,
): ColumnDef<ForgejoRepository>[] => [
  {
    accessorKey: "displayName",
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(false)}
          className="h-auto px-0 py-0 hover:bg-transparent hover:text-[color:var(--accent)]"
        >
          Repository
          {column.getIsSorted() === "asc" && "↑"}
          {column.getIsSorted() === "desc" && "↓"}
        </Button>
      );
    },
    cell: ({ row }) => {
      const repo = row.original;
      const tone = repositoryTone(repo);
      return (
        <div className="flex min-w-[280px] items-start gap-3">
          <div
            className={cn(
              "mt-0.5 rounded-xl border p-2 shadow-[0_0_22px_rgba(96,165,250,0.08)]",
              toneClasses[tone].icon,
            )}
          >
            <GitBranch className="h-4 w-4" />
          </div>
          <div className="min-w-0">
            <div className="flex min-w-0 flex-wrap items-center gap-2">
              <span className="truncate font-semibold text-strong">
                {repositoryLabel(repo)}
              </span>
              {repo.default_branch ? (
                <span className="inline-flex items-center gap-1 rounded-full border border-[color:rgba(96,165,250,0.26)] bg-[color:rgba(96,165,250,0.1)] px-2 py-0.5 font-mono text-[11px] text-[color:var(--accent-strong)]">
                  <GitCommitHorizontal className="h-3 w-3" />
                  {repo.default_branch}
                </span>
              ) : null}
            </div>
            <span className="mt-1 flex min-w-0 items-center gap-1 truncate font-mono text-xs text-muted">
              <GitFork className="h-3 w-3 shrink-0" />
              <span className="truncate">
                {repo.owner}/{repo.repo}
              </span>
              {repo.connection?.name ? (
                <span className="truncate text-[color:var(--text-quiet)]">
                  / {repo.connection.name}
                </span>
              ) : null}
            </span>
            {repo.description ? (
              <span className="mt-1 block max-w-[360px] truncate text-xs text-muted">
                {repo.description}
              </span>
            ) : null}
            {repo.topics.length ? (
              <div className="mt-2 flex max-w-[360px] flex-wrap gap-1.5">
                {repo.topics.slice(0, 3).map((topic) => (
                  <Badge
                    key={topic}
                    variant="accent"
                    className="h-5 rounded-full px-2 text-[11px] normal-case"
                  >
                    {topic}
                  </Badge>
                ))}
                {repo.topics.length > 3 ? (
                  <Badge
                    variant="outline"
                    className="h-5 rounded-full px-2 text-[11px]"
                  >
                    +{repo.topics.length - 3}
                  </Badge>
                ) : null}
              </div>
            ) : null}
          </div>
        </div>
      );
    },
  },
  {
    accessorKey: "connection",
    header: "Connection",
    cell: ({ row }) => {
      const connection = row.original.connection;
      return (
        <div className="min-w-[180px]">
          <span className="block truncate font-medium text-sm text-strong">
            {connection?.name}
          </span>
          <span className="mt-1 inline-flex max-w-[240px] items-center rounded-full border border-[color:var(--border)] bg-[color:var(--surface-muted)] px-2 py-0.5 font-mono text-[11px] text-muted">
            {connection?.base_url}
          </span>
        </div>
      );
    },
  },
  {
    accessorKey: "status",
    header: "Status",
    cell: ({ row }) => {
      const repo = row.original;
      const isActive = repo.active;
      return (
        <div className="flex max-w-[230px] flex-wrap gap-1.5">
          <Badge variant={isActive ? "success" : "outline"} className="gap-1">
            <span
              className={cn(
                "h-1.5 w-1.5 rounded-full",
                isActive
                  ? "bg-[color:var(--success)]"
                  : "bg-[color:var(--text-quiet)]",
              )}
            />
            {isActive ? "Active" : "Inactive"}
          </Badge>
          {repo.is_archived ? (
            <Badge variant="warning" className="gap-1">
              <Archive className="h-3 w-3" />
              Archived
            </Badge>
          ) : null}
          {repo.has_webhook_secret ? (
            <Badge variant="success" className="gap-1">
              <KeyRound className="h-3 w-3" />
              Webhook
            </Badge>
          ) : (
            <Badge variant="outline" className="gap-1">
              <KeyRound className="h-3 w-3" />
              No secret
            </Badge>
          )}
          {repo.last_sync_error ? (
            <Badge variant="danger" className="gap-1">
              <AlertCircle className="h-3 w-3" />
              Sync error
            </Badge>
          ) : repo.last_sync_at ? (
            <Badge variant="accent" className="gap-1">
              <ShieldCheck className="h-3 w-3" />
              Synced
            </Badge>
          ) : (
            <Badge variant="warning" className="gap-1">
              <CircleDot className="h-3 w-3" />
              New
            </Badge>
          )}
        </div>
      );
    },
  },
  {
    accessorKey: "openIssues",
    header: "Issues",
    cell: ({ row }) => (
      <div
        className={cn(
          "inline-flex min-w-[94px] flex-col rounded-xl border px-3 py-2",
          row.original.open_issues_count > 0
            ? "border-[color:rgba(251,191,36,0.28)] bg-[color:rgba(251,191,36,0.1)]"
            : "border-[color:rgba(52,211,153,0.24)] bg-[color:rgba(52,211,153,0.08)]",
        )}
      >
        <span className="text-lg font-semibold leading-none text-strong">
          {row.original.open_issues_count}
        </span>
        <span className="mt-1 text-[11px] uppercase tracking-wide text-muted">
          open
        </span>
      </div>
    ),
  },
  {
    accessorKey: "lastSync",
    header: "Last Sync",
    cell: ({ row }) => {
      const lastSyncAt = row.original.last_sync_at;
      const lastSyncError = row.original.last_sync_error;
      const tone = repositoryTone(row.original);
      const syncTime = formatSyncTime(lastSyncAt);

      if (!syncTime) {
        return (
          <div className="flex items-center gap-2 text-sm text-muted">
            <span
              className={cn("h-2 w-2 rounded-full", toneClasses[tone].dot)}
            />
            Never
          </div>
        );
      }

      return (
        <div className="flex min-w-[150px] items-start gap-2">
          <span
            className={cn("mt-1.5 h-2 w-2 rounded-full", toneClasses[tone].dot)}
          />
          <div className="flex flex-col">
            <span className="text-sm font-medium text-strong">
              {syncTime.date}
            </span>
            <span className="text-xs text-muted">{syncTime.time}</span>
            {lastSyncError && (
              <span className="max-w-[220px] truncate text-xs text-[color:var(--danger)]">
                Error: {lastSyncError.substring(0, 50)}...
              </span>
            )}
          </div>
        </div>
      );
    },
  },
  {
    id: "actions",
    cell: ({ row }) => (
      <ActionsCell
        repository={row.original}
        onSync={onSync}
        onValidate={onValidate}
        onViewDetails={onViewDetails}
      />
    ),
  },
];

function ActionsCell({
  repository,
  onSync,
  onValidate,
  onViewDetails,
}: {
  repository: ForgejoRepository;
  onSync?: (repository: ForgejoRepository) => Promise<RepositorySyncResult>;
  onValidate?: (
    repository: ForgejoRepository,
  ) => Promise<ForgejoRepositoryValidationResponse>;
  onViewDetails?: (repository: ForgejoRepository) => void;
}) {
  const [isSyncLoading, setIsSyncLoading] = useState(false);
  const [isValidateLoading, setIsValidateLoading] = useState(false);
  const [syncResult, setSyncResult] = useState<{
    created: number;
    updated: number;
    open: number;
    closed: number;
    total: number;
  } | null>(null);
  const [validateResult, setValidateResult] = useState<{
    ok: boolean;
    repo_exists?: boolean;
    error_message?: string;
  } | null>(null);

  const handleSync = async () => {
    if (!onSync) return;
    setIsSyncLoading(true);
    try {
      const result = await onSync(repository);
      setSyncResult(result);
    } finally {
      setIsSyncLoading(false);
    }
  };

  const handleValidate = async () => {
    if (!onValidate) return;
    setIsValidateLoading(true);
    try {
      const result = await onValidate(repository);
      setValidateResult({
        ok: result.status.ok,
        repo_exists: result.repo_exists ?? undefined,
        error_message: result.status.error_message ?? undefined,
      });
    } finally {
      setIsValidateLoading(false);
    }
  };

  return (
    <div className="flex items-center gap-2">
      {onSync && (
        <Button
          variant="ghost"
          onClick={handleSync}
          disabled={isSyncLoading}
          className="h-8 w-8 p-0"
          title="Sync issues"
          aria-label={`Sync issues for ${repository.display_name || `${repository.owner}/${repository.repo}`}`}
        >
          {isSyncLoading ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : syncResult ? (
            <CheckCircle2 className="h-4 w-4 text-[color:var(--success)]" />
          ) : (
            <RefreshCw className="h-4 w-4" />
          )}
        </Button>
      )}
      {onValidate && (
        <Button
          variant="ghost"
          onClick={handleValidate}
          disabled={isValidateLoading}
          className="h-8 w-8 p-0"
          title="Validate repository"
          aria-label={`Validate ${repository.display_name || `${repository.owner}/${repository.repo}`}`}
        >
          {isValidateLoading ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : validateResult?.ok ? (
            <CheckCircle2 className="h-4 w-4 text-[color:var(--success)]" />
          ) : (
            <CheckCircle2 className="h-4 w-4" />
          )}
        </Button>
      )}
      {onViewDetails && (
        <Button
          variant="ghost"
          onClick={() => onViewDetails(repository)}
          className="h-8 w-8 p-0"
          title="Repository details"
          aria-label={`View details for ${repository.display_name || `${repository.owner}/${repository.repo}`}`}
        >
          <Eye className="h-4 w-4" />
        </Button>
      )}
    </div>
  );
}

// Filter component
export function RepositoriesTableFilter({
  value,
  onChange,
}: {
  value: string;
  onChange: (value: string) => void;
}) {
  return (
    <input
      type="text"
      placeholder="Filter repositories…"
      value={value ?? ""}
      onChange={(e) => onChange(e.target.value)}
      className="h-9 w-[150px] rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] px-3 py-1 text-sm text-strong focus:border-[color:var(--accent)] focus:outline-none focus:ring-2 focus:ring-[color:var(--accent)] lg:w-[250px]"
    />
  );
}

// Column toggle component
export function RepositoriesTableToggle({
  table,
}: {
  table: TableType<ForgejoRepository>;
}) {
  return (
    <div className="flex items-center gap-2">
      <div className="flex items-center gap-2">
        <span className="text-xs text-muted">Show:</span>
        <Button
          variant="ghost"
          size="sm"
          onClick={() => table.toggleAllColumnsVisible()}
          className="h-8 px-2 py-1 text-xs"
        >
          All
        </Button>
        <Button
          variant="ghost"
          size="sm"
          onClick={() => table.toggleAllColumnsVisible(false)}
          className="h-8 px-2 py-1 text-xs"
        >
          None
        </Button>
      </div>
      <div className="flex gap-1">
        {table
          .getAllColumns()
          .filter((column) => column.getCanHide())
          .map((column) => {
            return (
              <Button
                key={column.id}
                variant="ghost"
                size="sm"
                onClick={() => column.toggleVisibility(!column.getIsVisible())}
                className={cn(
                  "h-8 px-2 py-1 text-xs",
                  column.getIsVisible()
                    ? "bg-[color:var(--surface-strong)] text-strong"
                    : "text-muted",
                )}
              >
                {column.id}
              </Button>
            );
          })}
      </div>
    </div>
  );
}
