"use client";

import {
  useCallback,
  useEffect,
  useState,
  type ChangeEvent,
  type ReactElement,
  type SyntheticEvent,
} from "react";
import { Pencil, Trash2 } from "lucide-react";
import { FleetSettingsNav } from "@/components/settings/FleetSettingsNav";
import {
  createAgentProvider,
  deleteAgentProvider,
  fetchAgentProviders,
  updateAgentProvider,
  type AgentProviderConfig,
  type CreateAgentProviderRequest,
  type UpdateAgentProviderRequest,
} from "@/lib/api/agent-providers";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";

interface ProviderFormData {
  name: string;
  provider: "openclaw";
  gatewayUrl: string;
  apiToken: string;
  isActive: boolean;
}

const NAME_PATTERN = /^[a-zA-Z0-9-]+$/;

const INITIAL_FORM: ProviderFormData = {
  name: "",
  provider: "openclaw",
  gatewayUrl: "",
  apiToken: "",
  isActive: true,
};

function getErrorMessage(error: unknown, fallback: string): string {
  if (error instanceof Error && error.message.trim().length > 0) {
    return error.message;
  }

  return fallback;
}

function isValidHttpsUrl(value: string): boolean {
  try {
    const parsed = new URL(value);
    return parsed.protocol === "https:";
  } catch {
    return false;
  }
}

function formatCreatedDate(value: string): string {
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) {
    return "Unknown";
  }

  return new Intl.DateTimeFormat(undefined, {
    year: "numeric",
    month: "short",
    day: "numeric",
  }).format(parsed);
}

function validateForm(form: ProviderFormData, isEditing: boolean): string | null {
  const name = form.name.trim();
  if (name.length === 0) {
    return "Name is required.";
  }

  if (!NAME_PATTERN.test(name)) {
    return "Name must contain only letters, numbers, and hyphens.";
  }

  const gatewayUrl = form.gatewayUrl.trim();
  if (gatewayUrl.length === 0) {
    return "Gateway URL is required.";
  }

  if (!isValidHttpsUrl(gatewayUrl)) {
    return "Gateway URL must be a valid https:// URL.";
  }

  if (!isEditing && form.apiToken.trim().length === 0) {
    return "API token is required when creating a provider.";
  }

  return null;
}

export default function AgentProvidersSettingsPage(): ReactElement {
  const [providers, setProviders] = useState<AgentProviderConfig[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);

  const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
  const [editingProvider, setEditingProvider] = useState<AgentProviderConfig | null>(null);
  const [form, setForm] = useState<ProviderFormData>(INITIAL_FORM);
  const [formError, setFormError] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState<boolean>(false);

  const [deleteTarget, setDeleteTarget] = useState<AgentProviderConfig | null>(null);
  const [isDeleting, setIsDeleting] = useState<boolean>(false);

  const loadProviders = useCallback(async (showLoadingState: boolean): Promise<void> => {
    if (showLoadingState) {
      setIsLoading(true);
    } else {
      setIsRefreshing(true);
    }

    try {
      const data = await fetchAgentProviders();
      setProviders(data);
      setError(null);
    } catch (loadError: unknown) {
      setError(getErrorMessage(loadError, "Failed to load agent providers."));
    } finally {
      setIsLoading(false);
      setIsRefreshing(false);
    }
  }, []);

  useEffect(() => {
    void loadProviders(true);
  }, [loadProviders]);

  function openCreateDialog(): void {
    setEditingProvider(null);
    setForm(INITIAL_FORM);
    setFormError(null);
    setIsDialogOpen(true);
  }

  function openEditDialog(provider: AgentProviderConfig): void {
    setEditingProvider(provider);
    setForm({
      name: provider.name,
      provider: "openclaw",
      gatewayUrl: provider.gatewayUrl,
      apiToken: "",
      isActive: provider.isActive,
    });
    setFormError(null);
    setIsDialogOpen(true);
  }

  function closeDialog(): void {
    if (isSaving) {
      return;
    }

    setIsDialogOpen(false);
    setEditingProvider(null);
    setForm(INITIAL_FORM);
    setFormError(null);
  }

  async function handleSubmit(event: SyntheticEvent): Promise<void> {
    event.preventDefault();
    setFormError(null);
    setSuccessMessage(null);

    const validationError = validateForm(form, editingProvider !== null);
    if (validationError !== null) {
      setFormError(validationError);
      return;
    }

    const name = form.name.trim();
    const gatewayUrl = form.gatewayUrl.trim();
    const apiToken = form.apiToken.trim();

    try {
      setIsSaving(true);

      if (editingProvider) {
        const updatePayload: UpdateAgentProviderRequest = {
          name,
          provider: form.provider,
          gatewayUrl,
          isActive: form.isActive,
        };

        if (apiToken.length > 0) {
          updatePayload.credentials = { apiToken };
        }

        await updateAgentProvider(editingProvider.id, updatePayload);
        setSuccessMessage(`Updated provider "${name}".`);
      } else {
        const createPayload: CreateAgentProviderRequest = {
          name,
          provider: form.provider,
          gatewayUrl,
          credentials: { apiToken },
          isActive: form.isActive,
        };

        await createAgentProvider(createPayload);
        setSuccessMessage(`Added provider "${name}".`);
      }

      setIsDialogOpen(false);
      setEditingProvider(null);
      setForm(INITIAL_FORM);
      await loadProviders(false);
    } catch (saveError: unknown) {
      setFormError(getErrorMessage(saveError, "Unable to save agent provider."));
    } finally {
      setIsSaving(false);
    }
  }

  async function handleDeleteProvider(): Promise<void> {
    if (!deleteTarget) {
      return;
    }

    try {
      setIsDeleting(true);
      await deleteAgentProvider(deleteTarget.id);
      setSuccessMessage(`Deleted provider "${deleteTarget.name}".`);
      setDeleteTarget(null);
      await loadProviders(false);
    } catch (deleteError: unknown) {
      setError(getErrorMessage(deleteError, "Failed to delete agent provider."));
    } finally {
      setIsDeleting(false);
    }
  }

  return (
    <div className="max-w-6xl mx-auto p-6 space-y-6">
      <div className="space-y-4">
        <div>
          <h1 className="text-3xl font-bold">Agent Providers</h1>
          <p className="text-muted-foreground mt-1">
            Register OpenClaw gateways and API tokens used for external agent sessions.
          </p>
        </div>
        <FleetSettingsNav />
      </div>

      <Card>
        <CardHeader className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <CardTitle>OpenClaw Gateways</CardTitle>
            <CardDescription>
              Add one or more OpenClaw gateway endpoints and control which ones are active.
            </CardDescription>
          </div>
          <div className="flex items-center gap-2">
            <Button
              variant="outline"
              onClick={() => {
                void loadProviders(false);
              }}
              disabled={isLoading || isRefreshing}
            >
              {isRefreshing ? "Refreshing..." : "Refresh"}
            </Button>
            <Button onClick={openCreateDialog}>Add Provider</Button>
          </div>
        </CardHeader>

        <CardContent className="space-y-3">
          {error ? (
            <p className="text-sm text-destructive" role="alert">
              {error}
            </p>
          ) : null}

          {successMessage ? <p className="text-sm text-emerald-600">{successMessage}</p> : null}

          {isLoading ? (
            <p className="text-sm text-muted-foreground">Loading agent providers...</p>
          ) : providers.length === 0 ? (
            <p className="text-sm text-muted-foreground">
              No agent providers configured yet. Add one to register an OpenClaw gateway.
            </p>
          ) : (
            providers.map((provider) => (
              <div
                key={provider.id}
                className="rounded-lg border p-4 flex flex-col gap-4 md:flex-row md:items-start md:justify-between"
              >
                <div className="space-y-2 min-w-0">
                  <div className="flex items-center gap-2 flex-wrap">
                    <p className="font-semibold truncate">{provider.name}</p>
                    <Badge variant={provider.isActive ? "default" : "secondary"}>
                      {provider.isActive ? "Active" : "Inactive"}
                    </Badge>
                    <Badge variant="outline">{provider.provider}</Badge>
                  </div>
                  <p className="text-sm text-muted-foreground break-all">
                    Gateway URL: {provider.gatewayUrl}
                  </p>
                  <p className="text-sm text-muted-foreground">
                    Created: {formatCreatedDate(provider.createdAt)}
                  </p>
                </div>

                <div className="flex items-center gap-2">
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => {
                      openEditDialog(provider);
                    }}
                  >
                    <Pencil className="h-4 w-4 mr-2" />
                    Edit
                  </Button>
                  <Button
                    variant="destructive"
                    size="sm"
                    onClick={() => {
                      setDeleteTarget(provider);
                    }}
                  >
                    <Trash2 className="h-4 w-4 mr-2" />
                    Delete
                  </Button>
                </div>
              </div>
            ))
          )}
        </CardContent>
      </Card>

      <Dialog
        open={isDialogOpen}
        onOpenChange={(nextOpen) => {
          if (!nextOpen) {
            closeDialog();
            return;
          }

          setIsDialogOpen(true);
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>
              {editingProvider ? "Edit Agent Provider" : "Add Agent Provider"}
            </DialogTitle>
            <DialogDescription>
              Configure an OpenClaw gateway URL and API token for agent provider registration.
            </DialogDescription>
          </DialogHeader>

          <form onSubmit={(event) => void handleSubmit(event)} className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="agent-provider-name">Name</Label>
              <Input
                id="agent-provider-name"
                value={form.name}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setForm((previous) => ({ ...previous, name: event.target.value }));
                }}
                placeholder="openclaw-primary"
                maxLength={100}
                disabled={isSaving}
                required
              />
              <p className="text-xs text-muted-foreground">
                Use letters, numbers, and hyphens only.
              </p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="agent-provider-type">Provider Type</Label>
              <Select
                value={form.provider}
                onValueChange={(value) => {
                  if (value === "openclaw") {
                    setForm((previous) => ({ ...previous, provider: value }));
                  }
                }}
                disabled={isSaving}
              >
                <SelectTrigger id="agent-provider-type">
                  <SelectValue placeholder="Select provider type" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="openclaw">openclaw</SelectItem>
                </SelectContent>
              </Select>
            </div>

            <div className="space-y-2">
              <Label htmlFor="agent-provider-gateway-url">Gateway URL</Label>
              <Input
                id="agent-provider-gateway-url"
                value={form.gatewayUrl}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setForm((previous) => ({ ...previous, gatewayUrl: event.target.value }));
                }}
                placeholder="https://my-openclaw.example.com"
                disabled={isSaving}
                required
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="agent-provider-api-token">API Token</Label>
              <Input
                id="agent-provider-api-token"
                type="password"
                value={form.apiToken}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setForm((previous) => ({ ...previous, apiToken: event.target.value }));
                }}
                placeholder={
                  editingProvider ? "Leave blank to keep existing token" : "Enter API token"
                }
                autoComplete="new-password"
                disabled={isSaving}
              />
              <p className="text-xs text-muted-foreground">
                {editingProvider
                  ? "Leave blank to keep the currently stored token."
                  : "Required when creating a provider."}
              </p>
            </div>

            <div className="flex items-center justify-between rounded-md border px-3 py-2">
              <div>
                <Label htmlFor="agent-provider-active">Provider Status</Label>
                <p className="text-xs text-muted-foreground">
                  Inactive providers remain saved but are excluded from routing.
                </p>
              </div>
              <Switch
                id="agent-provider-active"
                checked={form.isActive}
                onCheckedChange={(checked) => {
                  setForm((previous) => ({ ...previous, isActive: checked }));
                }}
                disabled={isSaving}
              />
            </div>

            {formError ? (
              <p className="text-sm text-destructive" role="alert">
                {formError}
              </p>
            ) : null}

            <DialogFooter>
              <Button type="button" variant="outline" onClick={closeDialog} disabled={isSaving}>
                Cancel
              </Button>
              <Button type="submit" disabled={isSaving}>
                {isSaving ? "Saving..." : editingProvider ? "Save Changes" : "Create Provider"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <AlertDialog
        open={deleteTarget !== null}
        onOpenChange={(open) => {
          if (!open && !isDeleting) {
            setDeleteTarget(null);
          }
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete Agent Provider</AlertDialogTitle>
            <AlertDialogDescription>
              Delete provider "{deleteTarget?.name}"? This permanently removes its gateway and token
              configuration.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={isDeleting}>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={handleDeleteProvider} disabled={isDeleting}>
              {isDeleting ? "Deleting..." : "Delete Provider"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
