"use client";

import { useState } from "react";
import {
  useProviderConfigs,
  useCreateProvider,
  useUpdateProvider,
  useDeleteProvider,
  useTestProvider,
} from "@/hooks/use-admin-providers";
import { useConfig } from "@/hooks/use-config";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Badge } from "@/components/ui/badge";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { CheckCircle, XCircle, Loader2, Plus, Trash2 } from "lucide-react";
import { ApiRequestError } from "@/lib/api";
import type { ProviderConfig } from "@/lib/types";

const PROVIDER_FIELDS: Record<
  string,
  Array<{ key: string; label: string; type?: string; required?: boolean }>
> = {
  jellyfin: [
    { key: "base_url", label: "Base URL", required: true },
    { key: "api_key", label: "API Key", type: "password", required: true },
    { key: "user_id", label: "User ID", required: true },
  ],
  local_files: [
    { key: "files_dir", label: "Files Directory", required: true },
    { key: "transcode_dir", label: "Transcode Directory" },
    { key: "cleanup_ttl_hours", label: "Cleanup TTL Hours" },
  ],
};

function isValidInstanceId(id: string): boolean {
  return id.length >= 1 && id.length <= 40 && /^[a-zA-Z0-9-]+$/.test(id);
}

// ---------------------------------------------------------------------------
// Existing instance card
// ---------------------------------------------------------------------------

interface ProviderCardProps {
  config: ProviderConfig;
  existingIds: string[];
}

function ProviderCard({ config }: ProviderCardProps) {
  const fields = PROVIDER_FIELDS[config.provider_type] ?? [];
  const [formValues, setFormValues] = useState<Record<string, string>>(
    () => config.config_json ?? {},
  );
  const [enabled, setEnabled] = useState(config.enabled);
  const [conflictError, setConflictError] = useState(false);
  const [testResult, setTestResult] = useState<{ ok: boolean; message: string } | null>(null);

  const updateProvider = useUpdateProvider();
  const deleteProvider = useDeleteProvider();
  const testProvider = useTestProvider();

  const handleSave = async () => {
    setConflictError(false);
    try {
      await updateProvider.mutateAsync({
        id: config.id,
        payload: { config_json: formValues, enabled },
      });
    } catch (e: unknown) {
      if (e instanceof ApiRequestError && e.status === 409) {
        setConflictError(true);
      }
    }
  };

  const handleTest = async () => {
    setTestResult(null);
    const result = await testProvider.mutateAsync({
      provider_type: config.provider_type,
      config_json: formValues,
    });
    setTestResult(result);
  };

  const handleDelete = async () => {
    if (!confirm(`Delete provider instance "${config.id}"?`)) return;
    await deleteProvider.mutateAsync(config.id);
  };

  return (
    <Card className="border-zinc-800 bg-zinc-900">
      <CardHeader className="flex flex-row items-center justify-between pb-3">
        <div className="flex items-center gap-2">
          <Badge variant="outline" className="font-mono text-xs text-zinc-300 border-zinc-600">
            {config.id}
          </Badge>
          <span className="text-xs text-zinc-500 capitalize">
            {config.provider_type.replace("_", " ")}
          </span>
        </div>
        <div className="flex items-center gap-2">
          <span className="text-xs text-zinc-400">Enabled</span>
          <Switch checked={enabled} onCheckedChange={setEnabled} />
          <Button
            variant="ghost"
            size="icon"
            onClick={handleDelete}
            disabled={deleteProvider.isPending}
            className="h-7 w-7 text-zinc-500 hover:text-red-400"
          >
            {deleteProvider.isPending ? (
              <Loader2 className="h-3.5 w-3.5 animate-spin" />
            ) : (
              <Trash2 className="h-3.5 w-3.5" />
            )}
          </Button>
        </div>
      </CardHeader>
      <CardContent className="space-y-3">
        {conflictError && (
          <div className="rounded border border-yellow-600/40 bg-yellow-950/30 px-3 py-2 text-xs text-yellow-400">
            UI config disabled — set <code>CONFIG_SOURCE=db</code> on the server
          </div>
        )}
        {fields.map((field) => (
          <div key={field.key} className="space-y-1">
            <Label className="text-xs text-zinc-400">
              {field.label}
              {field.required && <span className="ml-1 text-red-400">*</span>}
            </Label>
            <Input
              type={field.type ?? "text"}
              value={formValues[field.key] ?? ""}
              onChange={(e) =>
                setFormValues((prev) => ({ ...prev, [field.key]: e.target.value }))
              }
              placeholder={
                field.type === "password" ? "••••••••" : `Enter ${field.label.toLowerCase()}`
              }
              className="h-8 border-zinc-700 bg-zinc-800 text-xs text-zinc-100"
            />
          </div>
        ))}
        {testResult && (
          <div
            className={`flex items-center gap-2 rounded px-3 py-2 text-xs ${
              testResult.ok
                ? "bg-green-950/30 text-green-400"
                : "bg-red-950/30 text-red-400"
            }`}
          >
            {testResult.ok ? (
              <CheckCircle className="h-3.5 w-3.5" />
            ) : (
              <XCircle className="h-3.5 w-3.5" />
            )}
            {testResult.message}
          </div>
        )}
        <div className="flex gap-2 pt-1">
          <Button
            variant="outline"
            size="sm"
            onClick={handleTest}
            disabled={testProvider.isPending}
            className="border-zinc-700 text-xs"
          >
            {testProvider.isPending && <Loader2 className="mr-1 h-3 w-3 animate-spin" />}
            Test Connection
          </Button>
          <Button
            size="sm"
            onClick={handleSave}
            disabled={updateProvider.isPending}
            className="text-xs"
          >
            {updateProvider.isPending && <Loader2 className="mr-1 h-3 w-3 animate-spin" />}
            Save
          </Button>
        </div>
      </CardContent>
    </Card>
  );
}

// ---------------------------------------------------------------------------
// Add Instance dialog
// ---------------------------------------------------------------------------

interface AddInstanceDialogProps {
  open: boolean;
  onClose: () => void;
  availableTypes: string[];
  existingIds: string[];
}

function AddInstanceDialog({ open, onClose, availableTypes, existingIds }: AddInstanceDialogProps) {
  const [instanceId, setInstanceId] = useState("");
  const [providerType, setProviderType] = useState(availableTypes[0] ?? "");
  const [formValues, setFormValues] = useState<Record<string, string>>({});
  const [idError, setIdError] = useState<string | null>(null);
  const [apiError, setApiError] = useState<string | null>(null);

  const createProvider = useCreateProvider();
  const testProvider = useTestProvider();
  const [testResult, setTestResult] = useState<{ ok: boolean; message: string } | null>(null);

  const fields = PROVIDER_FIELDS[providerType] ?? [];

  const handleTypeChange = (t: string) => {
    setProviderType(t);
    setFormValues({});
    setTestResult(null);
  };

  const validateId = (id: string): string | null => {
    if (!id) return "ID is required";
    if (!isValidInstanceId(id)) return "Only alphanumeric characters and hyphens, 1–40 chars";
    if (existingIds.includes(id)) return "An instance with this ID already exists";
    return null;
  };

  const handleCreate = async () => {
    const err = validateId(instanceId);
    if (err) { setIdError(err); return; }
    setIdError(null);
    setApiError(null);
    try {
      await createProvider.mutateAsync({
        id: instanceId,
        provider_type: providerType,
        config_json: formValues,
        enabled: true,
      });
      onClose();
      setInstanceId("");
      setFormValues({});
      setTestResult(null);
    } catch (e: unknown) {
      if (e instanceof ApiRequestError && e.status === 409) {
        setIdError("An instance with this ID already exists");
      } else if (e instanceof ApiRequestError) {
        setApiError(e.message);
      }
    }
  };

  const handleTest = async () => {
    setTestResult(null);
    const result = await testProvider.mutateAsync({
      provider_type: providerType,
      config_json: formValues,
    });
    setTestResult(result);
  };

  return (
    <Dialog open={open} onOpenChange={(v) => { if (!v) onClose(); }}>
      <DialogContent className="border-zinc-800 bg-zinc-950 text-zinc-100 max-w-md">
        <DialogHeader>
          <DialogTitle className="text-sm font-semibold">Add Provider Instance</DialogTitle>
        </DialogHeader>
        <div className="space-y-4 pt-2">
          <div className="space-y-1">
            <Label className="text-xs text-zinc-400">
              Instance ID <span className="text-red-400">*</span>
            </Label>
            <Input
              value={instanceId}
              onChange={(e) => {
                setInstanceId(e.target.value);
                setIdError(null);
              }}
              placeholder="e.g. jellyfin-main"
              className="h-8 border-zinc-700 bg-zinc-800 text-xs text-zinc-100 font-mono"
            />
            {idError && <p className="text-xs text-red-400">{idError}</p>}
            <p className="text-xs text-zinc-600">Alphanumeric + hyphens, 1–40 chars</p>
          </div>

          <div className="space-y-1">
            <Label className="text-xs text-zinc-400">
              Provider Type <span className="text-red-400">*</span>
            </Label>
            <Select value={providerType} onValueChange={handleTypeChange}>
              <SelectTrigger className="h-8 border-zinc-700 bg-zinc-800 text-xs text-zinc-100">
                <SelectValue />
              </SelectTrigger>
              <SelectContent className="border-zinc-700 bg-zinc-900">
                {availableTypes.map((t) => (
                  <SelectItem key={t} value={t} className="text-xs capitalize text-zinc-200">
                    {t.replace("_", " ")}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {fields.map((field) => (
            <div key={field.key} className="space-y-1">
              <Label className="text-xs text-zinc-400">
                {field.label}
                {field.required && <span className="ml-1 text-red-400">*</span>}
              </Label>
              <Input
                type={field.type ?? "text"}
                value={formValues[field.key] ?? ""}
                onChange={(e) =>
                  setFormValues((prev) => ({ ...prev, [field.key]: e.target.value }))
                }
                placeholder={
                  field.type === "password" ? "••••••••" : `Enter ${field.label.toLowerCase()}`
                }
                className="h-8 border-zinc-700 bg-zinc-800 text-xs text-zinc-100"
              />
            </div>
          ))}

          {testResult && (
            <div
              className={`flex items-center gap-2 rounded px-3 py-2 text-xs ${
                testResult.ok
                  ? "bg-green-950/30 text-green-400"
                  : "bg-red-950/30 text-red-400"
              }`}
            >
              {testResult.ok ? (
                <CheckCircle className="h-3.5 w-3.5" />
              ) : (
                <XCircle className="h-3.5 w-3.5" />
              )}
              {testResult.message}
            </div>
          )}

          {apiError && (
            <p className="text-xs text-red-400">{apiError}</p>
          )}

          <div className="flex gap-2 pt-1">
            <Button
              variant="outline"
              size="sm"
              onClick={handleTest}
              disabled={testProvider.isPending}
              className="border-zinc-700 text-xs"
            >
              {testProvider.isPending && <Loader2 className="mr-1 h-3 w-3 animate-spin" />}
              Test
            </Button>
            <Button
              size="sm"
              onClick={handleCreate}
              disabled={createProvider.isPending}
              className="text-xs"
            >
              {createProvider.isPending && <Loader2 className="mr-1 h-3 w-3 animate-spin" />}
              Create
            </Button>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  );
}

// ---------------------------------------------------------------------------
// Panel
// ---------------------------------------------------------------------------

export function ProviderSettingsPanel() {
  const { data: config } = useConfig();
  const { data: providerConfigs = [] } = useProviderConfigs();
  const [addOpen, setAddOpen] = useState(false);

  const availableTypes = config?.available_provider_types ?? [];
  const existingIds = providerConfigs.map((c) => c.id);

  return (
    <div className="space-y-4 p-6">
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-sm font-semibold text-zinc-100">Provider Instances</h2>
          <p className="mt-0.5 text-xs text-zinc-500">
            Manage media provider instances. Requires <code>CONFIG_SOURCE=db</code> on the server.
          </p>
        </div>
        {availableTypes.length > 0 && (
          <Button
            size="sm"
            variant="outline"
            onClick={() => setAddOpen(true)}
            className="border-zinc-700 text-xs gap-1"
          >
            <Plus className="h-3.5 w-3.5" />
            Add Instance
          </Button>
        )}
      </div>

      {availableTypes.length === 0 ? (
        <p className="text-xs text-zinc-500">No providers available in this build.</p>
      ) : providerConfigs.length === 0 ? (
        <p className="text-xs text-zinc-500">
          No provider instances configured. Click &quot;Add Instance&quot; to get started.
        </p>
      ) : (
        <div className="space-y-4">
          {providerConfigs.map((c) => (
            <ProviderCard key={c.id} config={c} existingIds={existingIds} />
          ))}
        </div>
      )}

      <AddInstanceDialog
        open={addOpen}
        onClose={() => setAddOpen(false)}
        availableTypes={availableTypes}
        existingIds={existingIds}
      />
    </div>
  );
}
