"use client";

export const dynamic = "force-dynamic";

import { useMemo, useRef, useState } from "react";
import { useParams, useRouter, useSearchParams } from "next/navigation";

import { useAuth } from "@/auth/clerk";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { AlertCircle, RefreshCw, Save } from "lucide-react";
import { AgentsTable } from "@/components/agents/AgentsTable";
import { DashboardPageLayout } from "@/components/templates/DashboardPageLayout";
import { Button } from "@/components/ui/button";
import { ConfirmActionDialog } from "@/components/ui/confirm-action-dialog";

import { ApiError } from "@/api/mutator";
import {
  type listBoardsApiV1BoardsGetResponse,
  useListBoardsApiV1BoardsGet,
} from "@/api/generated/boards/boards";
import {
  type gatewaysStatusApiV1GatewaysStatusGetResponse,
  type getGatewayApiV1GatewaysGatewayIdGetResponse,
  useGatewaysStatusApiV1GatewaysStatusGet,
  useGetGatewayApiV1GatewaysGatewayIdGet,
  getGatewayLogsApiV1GatewaysGatewayIdLogsGet,
  getGatewayConfigApiV1GatewaysGatewayIdConfigGet,
  patchGatewayConfigApiV1GatewaysGatewayIdConfigPatch,
} from "@/api/generated/gateways/gateways";
import {
  type listAgentsApiV1AgentsGetResponse,
  getListAgentsApiV1AgentsGetQueryKey,
  useDeleteAgentApiV1AgentsAgentIdDelete,
  useListAgentsApiV1AgentsGet,
} from "@/api/generated/agents/agents";
import { type AgentRead } from "@/api/generated/model";
import { formatTimestamp } from "@/lib/formatters";
import { createOptimisticListDeleteMutation } from "@/lib/list-delete";
import { useOrganizationMembership } from "@/lib/use-organization-membership";

const maskToken = (value?: string | null) => {
  if (!value) return "—";
  if (value.length <= 8) return "••••";
  return `••••${value.slice(-4)}`;
};

type TabKey = "overview" | "logs" | "config";

export default function GatewayDetailPage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const queryClient = useQueryClient();
  const params = useParams();
  const { isSignedIn } = useAuth();
  const gatewayIdParam = params?.gatewayId;
  const gatewayId = Array.isArray(gatewayIdParam)
    ? gatewayIdParam[0]
    : gatewayIdParam;

  const rawTab = searchParams.get("tab");
  const activeTab: TabKey =
    rawTab === "logs" || rawTab === "config" ? rawTab : "overview";

  const { isAdmin } = useOrganizationMembership(isSignedIn);
  const [deleteTarget, setDeleteTarget] = useState<AgentRead | null>(null);

  // ---- Logs tab state ----
  const logsQuery = useQuery({
    queryKey: ["gateway-logs", gatewayId],
    enabled: Boolean(isSignedIn && isAdmin && gatewayId && activeTab === "logs"),
    refetchOnMount: true,
    queryFn: () =>
      getGatewayLogsApiV1GatewaysGatewayIdLogsGet(gatewayId!, { lines: 200 }).then(
        (r) => (r.status === 200 ? (r.data as { lines: string[]; generated_at: string }) : null),
      ),
  });
  const logsEndRef = useRef<HTMLDivElement>(null);

  // ---- Config tab state ----
  const configQuery = useQuery({
    queryKey: ["gateway-config", gatewayId],
    enabled: Boolean(isSignedIn && isAdmin && gatewayId && activeTab === "config"),
    refetchOnMount: true,
    queryFn: () =>
      getGatewayConfigApiV1GatewaysGatewayIdConfigGet(gatewayId!).then(
        (r) =>
          r.status === 200
            ? (r.data as { config: Record<string, unknown>; available: boolean })
            : null,
      ),
  });
  const [configEdits, setConfigEdits] = useState<Record<string, string>>({});
  const [configSaveOpen, setConfigSaveOpen] = useState(false);
  const [configSaving, setConfigSaving] = useState(false);
  const [configSaveError, setConfigSaveError] = useState<string | null>(null);

  const handleConfigSave = async () => {
    if (!gatewayId || Object.keys(configEdits).length === 0) return;
    setConfigSaving(true);
    setConfigSaveError(null);
    try {
      await patchGatewayConfigApiV1GatewaysGatewayIdConfigPatch(gatewayId, configEdits);
      setConfigEdits({});
      setConfigSaveOpen(false);
      void configQuery.refetch();
    } catch (err) {
      setConfigSaveError(err instanceof Error ? err.message : "Config update failed.");
    } finally {
      setConfigSaving(false);
    }
  };
  const agentsKey = getListAgentsApiV1AgentsGetQueryKey(
    gatewayId ? { gateway_id: gatewayId } : undefined,
  );

  const gatewayQuery = useGetGatewayApiV1GatewaysGatewayIdGet<
    getGatewayApiV1GatewaysGatewayIdGetResponse,
    ApiError
  >(gatewayId ?? "", {
    query: {
      enabled: Boolean(isSignedIn && isAdmin && gatewayId),
      refetchInterval: 30_000,
    },
  });

  const gateway =
    gatewayQuery.data?.status === 200 ? gatewayQuery.data.data : null;

  const boardsQuery = useListBoardsApiV1BoardsGet<
    listBoardsApiV1BoardsGetResponse,
    ApiError
  >(undefined, {
    query: {
      enabled: Boolean(isSignedIn && isAdmin),
      refetchInterval: 30_000,
    },
  });

  const agentsQuery = useListAgentsApiV1AgentsGet<
    listAgentsApiV1AgentsGetResponse,
    ApiError
  >(gatewayId ? { gateway_id: gatewayId } : undefined, {
    query: {
      enabled: Boolean(isSignedIn && isAdmin && gatewayId),
      refetchInterval: 15_000,
    },
  });
  const deleteMutation = useDeleteAgentApiV1AgentsAgentIdDelete<
    ApiError,
    { previous?: listAgentsApiV1AgentsGetResponse }
  >(
    {
      mutation: createOptimisticListDeleteMutation<
        AgentRead,
        listAgentsApiV1AgentsGetResponse,
        { agentId: string }
      >({
        queryClient,
        queryKey: agentsKey,
        getItemId: (agent) => agent.id,
        getDeleteId: ({ agentId }) => agentId,
        onSuccess: () => {
          setDeleteTarget(null);
        },
        invalidateQueryKeys: [agentsKey],
      }),
    },
    queryClient,
  );

  const statusParams = gateway
    ? {
        gateway_url: gateway.url,
        gateway_token: gateway.token ?? undefined,
        gateway_disable_device_pairing: gateway.disable_device_pairing,
        gateway_allow_insecure_tls: gateway.allow_insecure_tls,
      }
    : {};

  const statusQuery = useGatewaysStatusApiV1GatewaysStatusGet<
    gatewaysStatusApiV1GatewaysStatusGetResponse,
    ApiError
  >(statusParams, {
    query: {
      enabled: Boolean(isSignedIn && isAdmin && gateway),
      refetchInterval: 15_000,
    },
  });

  const agents = useMemo(
    () =>
      agentsQuery.data?.status === 200
        ? (agentsQuery.data.data.items ?? [])
        : [],
    [agentsQuery.data],
  );
  const boards = useMemo(
    () =>
      boardsQuery.data?.status === 200
        ? (boardsQuery.data.data.items ?? [])
        : [],
    [boardsQuery.data],
  );

  const status =
    statusQuery.data?.status === 200 ? statusQuery.data.data : null;
  const isConnected = status?.connected ?? false;

  const title = useMemo(
    () => (gateway?.name ? gateway.name : "Gateway"),
    [gateway?.name],
  );
  const handleDelete = () => {
    if (!deleteTarget) return;
    deleteMutation.mutate({ agentId: deleteTarget.id });
  };

  return (
    <>
      <DashboardPageLayout
        signedOut={{
          message: "Sign in to view a gateway.",
          forceRedirectUrl: `/gateways/${gatewayId}`,
        }}
        title={title}
        description={
          activeTab === "logs"
            ? "Recent log output from the gateway process."
            : activeTab === "config"
              ? "Current gateway configuration. Secrets are masked."
              : "Gateway configuration and connection details."
        }
        headerActions={
          <div className="flex items-center gap-2">
            <Button variant="outline" onClick={() => router.push("/gateways")}>
              Back to gateways
            </Button>
            {isAdmin && gatewayId ? (
              <Button
                onClick={() => router.push(`/gateways/${gatewayId}/edit`)}
              >
                Edit gateway
              </Button>
            ) : null}
          </div>
        }
        isAdmin={isAdmin}
        adminOnlyMessage="Only organization owners and admins can access gateways."
      >
        {/* Tab bar */}
        {isAdmin && (
          <div className="mb-6 flex gap-1 border-b border-border pb-px">
            {(
              [
                { key: "overview", label: "Overview" },
                { key: "logs",     label: "Logs"     },
                { key: "config",   label: "Config"   },
              ] as const
            ).map(({ key, label }) => (
              <button
                key={key}
                type="button"
                onClick={() =>
                  router.push(
                    key === "overview"
                      ? `/gateways/${gatewayId}`
                      : `/gateways/${gatewayId}?tab=${key}`,
                  )
                }
                className={`rounded-t px-4 py-2 text-sm font-medium transition ${
                  activeTab === key
                    ? "border border-b-card border-border bg-card text-foreground"
                    : "text-muted-foreground hover:text-foreground"
                }`}
              >
                {label}
              </button>
            ))}
          </div>
        )}

        {/* Logs tab */}
        {activeTab === "logs" && isAdmin && (
          <div className="space-y-3">
            <div className="flex items-center justify-between">
              <p className="text-sm text-muted-foreground">
                {logsQuery.data ? `${logsQuery.data.lines.length} lines` : ""}
              </p>
              <Button
                variant="outline"
                size="sm"
                onClick={() => void logsQuery.refetch()}
                disabled={logsQuery.isFetching}
              >
                <RefreshCw
                  className={`mr-2 h-3.5 w-3.5 ${logsQuery.isFetching ? "animate-spin" : ""}`}
                />
                Refresh
              </Button>
            </div>
            {logsQuery.isLoading ? (
              <div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground">
                Loading logs…
              </div>
            ) : logsQuery.error ? (
              <div className="flex items-start gap-2 rounded-xl border border-destructive/40 bg-destructive/10 p-4 text-sm text-destructive">
                <AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />
                {logsQuery.error instanceof Error
                  ? logsQuery.error.message
                  : "Could not load logs."}
              </div>
            ) : (
              <div className="max-h-[60vh] overflow-y-auto rounded-xl border border-border bg-[#0d1117] p-4 font-mono text-xs leading-5">
                {(logsQuery.data?.lines ?? []).length === 0 ? (
                  <p className="text-muted-foreground">No log output available.</p>
                ) : (
                  (logsQuery.data?.lines ?? []).map((line, i) => {
                    const low = line.toLowerCase();
                    const cls = low.includes("error") || low.includes("err ")
                      ? "text-red-400"
                      : low.includes("warn")
                        ? "text-yellow-400"
                        : "text-slate-300";
                    return (
                      <div key={i} className={`whitespace-pre-wrap break-all ${cls}`}>
                        {line}
                      </div>
                    );
                  })
                )}
                <div ref={logsEndRef} />
              </div>
            )}
          </div>
        )}

        {/* Config tab */}
        {activeTab === "config" && isAdmin && (
          <div className="space-y-4">
            {configQuery.isLoading ? (
              <div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground">
                Loading config…
              </div>
            ) : configQuery.error ? (
              <div className="flex items-start gap-2 rounded-xl border border-destructive/40 bg-destructive/10 p-4 text-sm text-destructive">
                <AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />
                {configQuery.error instanceof Error
                  ? configQuery.error.message
                  : "Could not load config."}
              </div>
            ) : !configQuery.data?.available ? (
              <div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground">
                Config data is unavailable. The gateway may not expose its configuration via this API.
              </div>
            ) : (
              <>
                {Object.keys(configEdits).length > 0 && (
                  <div className="flex items-center justify-between rounded-lg border border-amber-300/50 bg-amber-50/10 px-4 py-2 text-sm text-amber-600">
                    <span>{Object.keys(configEdits).length} unsaved change{Object.keys(configEdits).length !== 1 ? "s" : ""}</span>
                    <div className="flex gap-2">
                      <Button variant="ghost" size="sm" onClick={() => setConfigEdits({})}>
                        Discard
                      </Button>
                      <Button
                        size="sm"
                        onClick={() => setConfigSaveOpen(true)}
                      >
                        <Save className="mr-2 h-3.5 w-3.5" />
                        Review &amp; save
                      </Button>
                    </div>
                  </div>
                )}
                <div className="rounded-xl border border-border bg-card overflow-hidden">
                  <table className="w-full text-sm">
                    <thead>
                      <tr className="border-b border-border bg-muted/50">
                        <th className="px-4 py-2.5 text-left text-xs font-semibold uppercase tracking-wide text-muted-foreground">Key</th>
                        <th className="px-4 py-2.5 text-left text-xs font-semibold uppercase tracking-wide text-muted-foreground">Value</th>
                      </tr>
                    </thead>
                    <tbody>
                      {Object.entries(configQuery.data.config).map(([key, rawValue]) => {
                        const displayValue = configEdits[key] ?? String(rawValue ?? "");
                        const isMasked = String(rawValue).startsWith("••••");
                        const isEdited = key in configEdits;
                        return (
                          <tr
                            key={key}
                            className={`border-b border-border last:border-0 ${isEdited ? "bg-amber-50/5" : ""}`}
                          >
                            <td className="px-4 py-2.5">
                              <code className="text-xs text-foreground">{key}</code>
                            </td>
                            <td className="px-4 py-2.5">
                              {isMasked ? (
                                <div className="flex items-center gap-2">
                                  <code className="text-xs text-muted-foreground">{String(rawValue)}</code>
                                  <input
                                    type="password"
                                    placeholder="Enter new value to change"
                                    value={configEdits[key] ?? ""}
                                    onChange={(e) => {
                                      const v = e.target.value;
                                      setConfigEdits((prev) =>
                                        v ? { ...prev, [key]: v } : Object.fromEntries(Object.entries(prev).filter(([k]) => k !== key)),
                                      );
                                    }}
                                    className="h-7 w-48 rounded border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring"
                                    autoComplete="new-password"
                                  />
                                </div>
                              ) : (
                                <input
                                  type="text"
                                  value={displayValue}
                                  onChange={(e) => {
                                    const v = e.target.value;
                                    setConfigEdits((prev) =>
                                      v !== String(rawValue ?? "")
                                        ? { ...prev, [key]: v }
                                        : Object.fromEntries(Object.entries(prev).filter(([k]) => k !== key)),
                                    );
                                  }}
                                  className={`h-7 w-full rounded border px-2 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring ${isEdited ? "border-amber-400 bg-amber-50/5" : "border-transparent bg-transparent hover:border-border"}`}
                                />
                              )}
                            </td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
              </>
            )}
          </div>
        )}

        {/* Config save confirmation */}
        <ConfirmActionDialog
          open={configSaveOpen}
          onOpenChange={setConfigSaveOpen}
          title="Apply config changes"
          description={
            Object.keys(configEdits).length > 0
              ? `You are about to change ${Object.keys(configEdits).length} setting${Object.keys(configEdits).length !== 1 ? "s" : ""}: ${Object.keys(configEdits).join(", ")}. The gateway will apply the changes immediately. This is logged.`
              : ""
          }
          onConfirm={handleConfigSave}
          isConfirming={configSaving}
          errorMessage={configSaveError}
          confirmLabel="Apply changes"
          confirmingLabel="Applying…"
          cancelLabel="Go back"
        />

        {/* Overview tab (existing content) */}
        {activeTab === "overview" && gatewayQuery.isLoading ? (
          <div className="rounded-xl border border-border bg-card p-6 text-sm text-muted-foreground shadow-sm">
            Loading gateway…
          </div>
        ) : activeTab === "overview" && gatewayQuery.error ? (
          <div className="rounded-xl border border-rose-200 bg-rose-50 p-6 text-sm text-rose-700">
            {gatewayQuery.error.message}
          </div>
        ) : activeTab === "overview" && gateway ? (
          <div className="space-y-6">
            <div className="grid gap-6 lg:grid-cols-2">
              <div className="rounded-xl border border-border bg-card p-6 shadow-sm">
                <div className="flex items-center justify-between">
                  <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                    Connection
                  </p>
                  <div className="flex items-center gap-2 text-xs text-muted-foreground">
                    <span
                      className={`h-2 w-2 rounded-full ${
                        statusQuery.isLoading
                          ? "bg-muted-foreground/40"
                          : isConnected
                            ? "bg-emerald-500"
                            : "bg-rose-500"
                      }`}
                    />
                    <span>
                      {statusQuery.isLoading
                        ? "Checking"
                        : isConnected
                          ? "Online"
                          : "Offline"}
                    </span>
                  </div>
                </div>
                <div className="mt-4 space-y-3 text-sm text-muted-foreground">
                  <div>
                    <p className="text-xs uppercase text-muted-foreground/70">
                      Gateway URL
                    </p>
                    <p className="mt-1 text-sm font-medium text-foreground">
                      {gateway.url}
                    </p>
                  </div>
                  <div>
                    <p className="text-xs uppercase text-muted-foreground/70">Token</p>
                    <p className="mt-1 text-sm font-medium text-foreground">
                      {maskToken(gateway.token)}
                    </p>
                  </div>
                  <div>
                    <p className="text-xs uppercase text-muted-foreground/70">
                      Device pairing
                    </p>
                    <p className="mt-1 text-sm font-medium text-foreground">
                      {gateway.disable_device_pairing ? "Disabled" : "Required"}
                    </p>
                  </div>
                </div>
              </div>

              <div className="rounded-xl border border-border bg-card p-6 shadow-sm">
                <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                  Runtime
                </p>
                <div className="mt-4 space-y-3 text-sm text-muted-foreground">
                  <div>
                    <p className="text-xs uppercase text-muted-foreground/70">
                      Workspace root
                    </p>
                    <p className="mt-1 text-sm font-medium text-foreground">
                      {gateway.workspace_root}
                    </p>
                  </div>
                  <div className="grid gap-3 sm:grid-cols-2">
                    <div>
                      <p className="text-xs uppercase text-muted-foreground/70">
                        Created
                      </p>
                      <p className="mt-1 text-sm font-medium text-foreground">
                        {formatTimestamp(gateway.created_at)}
                      </p>
                    </div>
                    <div>
                      <p className="text-xs uppercase text-muted-foreground/70">
                        Updated
                      </p>
                      <p className="mt-1 text-sm font-medium text-foreground">
                        {formatTimestamp(gateway.updated_at)}
                      </p>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div className="rounded-xl border border-border bg-card p-6 shadow-sm">
              <div className="flex items-center justify-between">
                <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                  Agents
                </p>
                {agentsQuery.isLoading ? (
                  <span className="text-xs text-muted-foreground">Loading…</span>
                ) : (
                  <span className="text-xs text-muted-foreground">
                    {agents.length} total
                  </span>
                )}
              </div>
              <div className="mt-4">
                <AgentsTable
                  agents={agents}
                  boards={boards}
                  isLoading={agentsQuery.isLoading}
                  onDelete={setDeleteTarget}
                  emptyMessage="No agents assigned to this gateway."
                />
              </div>
            </div>
          </div>
        ) : null}
      </DashboardPageLayout>

      <ConfirmActionDialog
        open={!!deleteTarget}
        onOpenChange={(open) => {
          if (!open) {
            setDeleteTarget(null);
          }
        }}
        ariaLabel="Delete agent"
        title="Delete agent"
        description={
          <>
            This will remove {deleteTarget?.name}. This action cannot be undone.
          </>
        }
        errorMessage={deleteMutation.error?.message}
        onConfirm={handleDelete}
        isConfirming={deleteMutation.isPending}
      />
    </>
  );
}
