"use client";

import {
  useCallback,
  useEffect,
  useMemo,
  useState,
  type ChangeEvent,
  type ReactElement,
  type SyntheticEvent,
} from "react";
import { Settings, Trash2 } from "lucide-react";
import { FleetSettingsNav } from "@/components/settings/FleetSettingsNav";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
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";
import { Textarea } from "@/components/ui/textarea";
import {
  createFleetProvider,
  deleteFleetProvider,
  fetchFleetProviders,
  updateFleetProvider,
  type CreateFleetProviderRequest,
  type FleetProvider,
  type FleetProviderModel,
  type UpdateFleetProviderRequest,
} from "@/lib/api/fleet-settings";

interface ProviderTypeOption {
  value: string;
  label: string;
}

interface ProviderFormState {
  type: string;
  displayName: string;
  apiKey: string;
  baseUrl: string;
  modelsText: string;
  isActive: boolean;
}

const PROVIDER_TYPE_OPTIONS: ProviderTypeOption[] = [
  { value: "openai", label: "OpenAI Compatible" },
  { value: "claude", label: "Claude / Anthropic" },
  { value: "ollama", label: "Ollama" },
  { value: "zai", label: "Z.ai" },
  { value: "custom", label: "Custom" },
];

const INITIAL_FORM: ProviderFormState = {
  type: "openai",
  displayName: "",
  apiKey: "",
  baseUrl: "",
  modelsText: "",
  isActive: true,
};

function mapProviderTypeToApi(type: string): "ollama" | "openai" | "claude" {
  if (type === "ollama" || type === "claude") {
    return type;
  }

  return "openai";
}

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

  return fallback;
}

function normalizeProviderModels(models: unknown): FleetProviderModel[] {
  if (!Array.isArray(models)) {
    return [];
  }

  const normalized: FleetProviderModel[] = [];

  models.forEach((entry) => {
    if (typeof entry === "string" && entry.trim().length > 0) {
      normalized.push({ id: entry.trim(), name: entry.trim() });
      return;
    }

    if (entry && typeof entry === "object") {
      const record = entry as Record<string, unknown>;
      const id =
        typeof record.id === "string"
          ? record.id.trim()
          : typeof record.name === "string"
            ? record.name.trim()
            : "";

      if (id.length > 0) {
        const name =
          typeof record.name === "string" && record.name.trim().length > 0
            ? record.name.trim()
            : id;
        normalized.push({ id, name });
      }
    }
  });

  const seen = new Set<string>();
  return normalized.filter((model) => {
    if (seen.has(model.id)) {
      return false;
    }
    seen.add(model.id);
    return true;
  });
}

function modelsToEditorText(models: unknown): string {
  return normalizeProviderModels(models)
    .map((model) => model.id)
    .join("\n");
}

function parseModelsText(value: string): string[] {
  const seen = new Set<string>();

  return value
    .split(/\r?\n/g)
    .map((segment) => segment.trim())
    .filter((segment) => segment.length > 0)
    .filter((segment) => {
      if (seen.has(segment)) {
        return false;
      }
      seen.add(segment);
      return true;
    });
}

function maskApiKey(value: string): string {
  if (value.length === 0) {
    return "Not set";
  }

  if (value.length <= 7) {
    return "*".repeat(Math.max(4, value.length));
  }

  return `${value.slice(0, 3)}****...${value.slice(-4)}`;
}

export default function ProvidersSettingsPage(): ReactElement {
  const [providers, setProviders] = useState<FleetProvider[]>([]);
  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<FleetProvider | null>(null);
  const [form, setForm] = useState<ProviderFormState>(INITIAL_FORM);
  const [formError, setFormError] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState<boolean>(false);

  const [deleteTarget, setDeleteTarget] = useState<FleetProvider | 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 fetchFleetProviders();
      setProviders(data);
      setError(null);
    } catch (loadError: unknown) {
      setError(getErrorMessage(loadError, "Failed to load providers."));
    } finally {
      setIsLoading(false);
      setIsRefreshing(false);
    }
  }, []);

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

  const apiKeyHint = useMemo(() => {
    const enteredKey = form.apiKey.trim();

    if (enteredKey.length > 0) {
      return `Masked preview: ${maskApiKey(enteredKey)}`;
    }

    if (editingProvider) {
      return "Stored API key remains encrypted and hidden. Enter a new key only when rotating.";
    }

    return "API keys are never shown decrypted. Only masked previews are displayed while typing.";
  }, [editingProvider, form.apiKey]);

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

  function openEditDialog(provider: FleetProvider): void {
    setEditingProvider(provider);
    setForm({
      type: provider.type,
      displayName: provider.displayName,
      apiKey: "",
      baseUrl: provider.baseUrl ?? "",
      modelsText: modelsToEditorText(provider.models),
      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 displayName = form.displayName.trim();
    if (displayName.length === 0) {
      setFormError("Display name is required.");
      return;
    }

    const models = parseModelsText(form.modelsText);
    const providerModels = models.map((id) => ({ id, name: id }));
    const baseUrl = form.baseUrl.trim();
    const apiKey = form.apiKey.trim();

    try {
      setIsSaving(true);

      if (editingProvider) {
        const updatePayload: UpdateFleetProviderRequest = {
          displayName,
          isActive: form.isActive,
          models: providerModels,
        };

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

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

        await updateFleetProvider(editingProvider.id, updatePayload);
        setSuccessMessage(`Updated provider "${displayName}".`);
      } else {
        const config: CreateFleetProviderRequest["config"] = {};

        if (baseUrl.length > 0) {
          config.endpoint = baseUrl;
        }

        if (apiKey.length > 0) {
          config.apiKey = apiKey;
        }

        if (models.length > 0) {
          config.models = models;
        }

        const createPayload: CreateFleetProviderRequest = {
          displayName,
          providerType: mapProviderTypeToApi(form.type),
          config,
          isEnabled: form.isActive,
        };

        await createFleetProvider(createPayload);
        setSuccessMessage(`Added provider "${displayName}".`);
      }

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

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

    try {
      setIsDeleting(true);
      await deleteFleetProvider(deleteTarget.id);
      setSuccessMessage(`Deleted provider "${deleteTarget.displayName}".`);
      setDeleteTarget(null);
      await loadProviders(false);
    } catch (deleteError: unknown) {
      setError(getErrorMessage(deleteError, "Failed to delete 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">LLM Providers</h1>
          <p className="text-muted-foreground mt-1">
            Manage provider endpoints, model inventories, and encrypted API credentials.
          </p>
        </div>
        <FleetSettingsNav />
      </div>

      <Card>
        <CardHeader className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <CardTitle>Provider Directory</CardTitle>
            <CardDescription>
              API keys are always encrypted in storage and never displayed in plaintext.
            </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 providers...</p>
          ) : providers.length === 0 ? (
            <p className="text-sm text-muted-foreground">
              No providers configured yet. Add one to make models available for agent assignment.
            </p>
          ) : (
            providers.map((provider) => {
              const providerModels = normalizeProviderModels(provider.models);

              return (
                <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.displayName}</p>
                      <Badge variant={provider.isActive ? "default" : "secondary"}>
                        {provider.isActive ? "Active" : "Inactive"}
                      </Badge>
                      <Badge variant="outline">{provider.type}</Badge>
                    </div>
                    <p className="text-sm text-muted-foreground">Name: {provider.name}</p>
                    <p className="text-sm text-muted-foreground">
                      Base URL: {provider.baseUrl ?? "Provider default"}
                    </p>
                    <p className="text-sm text-muted-foreground">
                      API Key: encrypted and hidden (never returned decrypted)
                    </p>
                    <div className="flex flex-wrap gap-2">
                      {providerModels.length === 0 ? (
                        <Badge variant="secondary">No models configured</Badge>
                      ) : (
                        providerModels.map((model) => (
                          <Badge key={`${provider.id}-${model.id}`} variant="outline">
                            {model.id}
                          </Badge>
                        ))
                      )}
                    </div>
                  </div>

                  <div className="flex items-center gap-2">
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => {
                        openEditDialog(provider);
                      }}
                    >
                      <Settings 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 Provider" : "Add Provider"}</DialogTitle>
            <DialogDescription>
              Configure connection details and model IDs. API keys are masked in the UI.
            </DialogDescription>
          </DialogHeader>

          <form onSubmit={(event) => void handleSubmit(event)} className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="provider-type">Type</Label>
              <Select
                value={form.type}
                onValueChange={(value) => {
                  setForm((previous) => ({ ...previous, type: value }));
                }}
                disabled={Boolean(editingProvider)}
              >
                <SelectTrigger id="provider-type">
                  <SelectValue placeholder="Select provider type" />
                </SelectTrigger>
                <SelectContent>
                  {PROVIDER_TYPE_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div className="space-y-2">
              <Label htmlFor="provider-display-name">Display Name</Label>
              <Input
                id="provider-display-name"
                value={form.displayName}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setForm((previous) => ({ ...previous, displayName: event.target.value }));
                }}
                placeholder="OpenAI Primary"
                maxLength={255}
                disabled={isSaving}
                required
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="provider-api-key">API Key</Label>
              <Input
                id="provider-api-key"
                type="password"
                value={form.apiKey}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setForm((previous) => ({ ...previous, apiKey: event.target.value }));
                }}
                placeholder={editingProvider ? "Enter new key to rotate" : "sk-..."}
                autoComplete="new-password"
                disabled={isSaving}
              />
              <p className="text-xs text-muted-foreground">{apiKeyHint}</p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="provider-base-url">Base URL</Label>
              <Input
                id="provider-base-url"
                value={form.baseUrl}
                onChange={(event: ChangeEvent<HTMLInputElement>) => {
                  setForm((previous) => ({ ...previous, baseUrl: event.target.value }));
                }}
                placeholder="https://api.provider.com/v1"
                disabled={isSaving}
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="provider-models">Models</Label>
              <Textarea
                id="provider-models"
                value={form.modelsText}
                onChange={(event: ChangeEvent<HTMLTextAreaElement>) => {
                  setForm((previous) => ({ ...previous, modelsText: event.target.value }));
                }}
                placeholder={"One model ID per line\nExample: gpt-4.1-mini"}
                rows={5}
                disabled={isSaving}
              />
            </div>

            {editingProvider ? (
              <div className="flex items-center justify-between rounded-md border px-3 py-2">
                <div>
                  <Label htmlFor="provider-active">Provider Status</Label>
                  <p className="text-xs text-muted-foreground">
                    Disable to keep configuration without using this provider.
                  </p>
                </div>
                <Switch
                  id="provider-active"
                  checked={form.isActive}
                  onCheckedChange={(checked) => {
                    setForm((previous) => ({ ...previous, isActive: checked }));
                  }}
                  disabled={isSaving}
                />
              </div>
            ) : null}

            {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 Provider</AlertDialogTitle>
            <AlertDialogDescription>
              Delete provider "{deleteTarget?.displayName}"? This removes its configuration and
              model mappings.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={isDeleting}>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={handleDeleteProvider} disabled={isDeleting}>
              {isDeleting ? "Deleting..." : "Delete Provider"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
