import { type JSX, useState, useEffect, useRef } from "react";
import { Button } from "../ui/button";
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
import { Eye, EyeOff, Copy, Check, ChevronDown } from "lucide-react";
import type { ProviderConfig } from "../../proxy/providers";
import { maskApiKey } from "../../lib/mask";

// Known provider presets - maps provider name keywords to their API URLs
const KNOWN_PROVIDER_PRESETS: Record<
  string,
  { format: "anthropic" | "openai"; baseUrl: string; apiDocsUrl?: string }
> = {
  deepseek: {
    format: "openai",
    baseUrl: "https://api.deepseek.com",
  },
  minimax: {
    format: "anthropic",
    baseUrl: "https://api.minimaxi.com/anthropic",
    apiDocsUrl: "https://platform.minimaxi.com/docs/api-reference/api-overview",
  },
  alibaba: {
    format: "openai",
    baseUrl: "https://dashscope.aliyuncs.com/compatible-mode",
  },
};

// MiniMax model options
const MINIMAX_MODELS = [
  "MiniMax M3",
  "MiniMax M2.7",
  "MiniMax M2.7-highspeed",
  "MiniMax M2.5",
  "MiniMax M2.5-highspeed",
  "MiniMax M2.1",
  "MiniMax M2.1-highspeed",
  "MiniMax M2",
];

// Alibaba model options
const ALIBABA_MODELS = ["glm-5", "glm-5.1", "qwen3.6-plus", "qwen3.7-max"];

type ProviderFormProps = {
  provider?: ProviderConfig;
  onSubmit: (data: {
    name: string;
    apiKey: string;
    models: string[];
    anthropicBaseUrl?: string;
    openaiBaseUrl?: string;
    apiDocsUrl?: string;
    source?: "company" | "personal";
  }) => void;
  onCancel: () => void;
};

export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps): JSX.Element {
  const [name, setName] = useState(provider?.name ?? "");
  const [apiKey, setApiKey] = useState(provider?.apiKey ?? "");
  const [showApiKey, setShowApiKey] = useState(false);
  const [copied, setCopied] = useState(false);
  const initialModels = provider?.models;
  const [models, setModels] = useState<string[]>(
    initialModels !== undefined && initialModels.length > 0 ? initialModels : [""],
  );
  const [activeTab, setActiveTab] = useState<"anthropic" | "openai">("anthropic");
  const [anthropicBaseUrl, setAnthropicBaseUrl] = useState(provider?.anthropicBaseUrl ?? "");
  const [openaiBaseUrl, setOpenaiBaseUrl] = useState(provider?.openaiBaseUrl ?? "");
  const [apiDocsUrl, setApiDocsUrl] = useState(provider?.apiDocsUrl ?? "");
  const [source, setSource] = useState<"company" | "personal" | undefined>(provider?.source);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [openModelDropdown, setOpenModelDropdown] = useState<number | null>(null);
  const modelRowRefs = useRef<(HTMLDivElement | null)[]>([]);

  // Close model dropdown when clicking outside
  useEffect(() => {
    if (openModelDropdown === null) return;
    const index = openModelDropdown;
    function handleClick(e: MouseEvent) {
      if (!(e.target instanceof Node)) return;
      const ref = modelRowRefs.current[index];
      if (ref !== null && ref !== undefined && !ref.contains(e.target)) {
        setOpenModelDropdown(null);
      }
    }
    document.addEventListener("mousedown", handleClick);
    return () => document.removeEventListener("mousedown", handleClick);
  }, [openModelDropdown]);

  // Track if URL fields have been manually edited (to avoid overriding user edits)
  const [manualAnthropicUrlOverride, setManualAnthropicUrlOverride] = useState(false);
  const [manualOpenaiUrlOverride, setManualOpenaiUrlOverride] = useState(false);

  // Check if MiniMax is detected
  const isMiniMax = name.toLowerCase().includes("minimax");
  // Check if Alibaba is detected
  const isAlibaba = name.toLowerCase().includes("alibaba");

  function handleCopy() {
    navigator.clipboard.writeText(apiKey).catch(() => {});
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  }

  useEffect(() => {
    if (provider) {
      setName(provider.name);
      setApiKey(provider.apiKey);
      setModels((provider.models?.length ?? 0) > 0 ? provider.models : [""]);
      setAnthropicBaseUrl(provider.anthropicBaseUrl ?? "");
      setOpenaiBaseUrl(provider.openaiBaseUrl ?? "");
      setApiDocsUrl(provider.apiDocsUrl ?? "");
      setSource(provider.source);
      setManualAnthropicUrlOverride(false);
      setManualOpenaiUrlOverride(false);
    }
  }, [provider]);

  // Detect known provider presets and auto-fill URLs
  useEffect(() => {
    const lowerName = name.toLowerCase();
    for (const [keyword, preset] of Object.entries(KNOWN_PROVIDER_PRESETS)) {
      if (lowerName.includes(keyword)) {
        if (preset.format === "anthropic" && !manualAnthropicUrlOverride) {
          setAnthropicBaseUrl(preset.baseUrl);
        } else if (preset.format === "openai" && !manualOpenaiUrlOverride) {
          setOpenaiBaseUrl(preset.baseUrl);
        }
        if (preset.apiDocsUrl !== undefined && !apiDocsUrl) {
          setApiDocsUrl(preset.apiDocsUrl);
        }
        // For MiniMax, auto-select the first model if not already set
        if (keyword === "minimax" && models.length === 1 && models[0] === "") {
          setModels([MINIMAX_MODELS[0] ?? ""]);
        }
        // For Alibaba, auto-select the first model if not already set
        if (keyword === "alibaba" && models.length === 1 && models[0] === "") {
          setModels([ALIBABA_MODELS[0] ?? ""]);
        }
        break;
      }
    }
  }, [name]);

  function validate(): boolean {
    const newErrors: Record<string, string> = {};
    if (!name.trim()) {
      newErrors.name = "Name is required";
    }
    if (!apiKey.trim()) {
      newErrors.apiKey = "API key is required";
    }
    if (models.length === 0 || models.every((m) => !m.trim())) {
      newErrors.models = "At least one model is required";
    }
    if (anthropicBaseUrl.trim() && !isValidUrl(anthropicBaseUrl.trim())) {
      newErrors.anthropicBaseUrl = "Invalid URL format";
    }
    if (openaiBaseUrl.trim() && !isValidUrl(openaiBaseUrl.trim())) {
      newErrors.openaiBaseUrl = "Invalid URL format";
    }
    if (!anthropicBaseUrl.trim() && !openaiBaseUrl.trim()) {
      newErrors.format = "At least one format URL (Anthropic or OpenAI) is required";
    }
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  }

  function isValidUrl(str: string): boolean {
    try {
      new URL(str);
      return true;
    } catch {
      return false;
    }
  }

  function handleSubmit(e: React.FormEvent): void {
    e.preventDefault();
    if (!validate()) return;
    setIsSubmitting(true);
    try {
      onSubmit({
        name: name.trim(),
        apiKey: apiKey.trim(),
        models: models.map((m) => m.trim()).filter((m) => m !== ""),
        anthropicBaseUrl: anthropicBaseUrl.trim() || undefined,
        openaiBaseUrl: openaiBaseUrl.trim() || undefined,
        apiDocsUrl: apiDocsUrl.trim() || undefined,
        source,
      });
    } finally {
      setIsSubmitting(false);
    }
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div className="space-y-2">
        <label htmlFor="provider-name" className="text-sm font-medium">
          Name <span className="text-destructive">*</span>
        </label>
        <input
          id="provider-name"
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Provider Name"
          className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
        />
        {errors.name !== undefined && <p className="text-xs text-destructive">{errors.name}</p>}
      </div>

      <div className="space-y-2">
        <label htmlFor="provider-source" className="text-sm font-medium">
          Token Source
        </label>
        <select
          id="provider-source"
          value={source ?? ""}
          onChange={(e) =>
            setSource(
              e.target.value === "company" || e.target.value === "personal"
                ? e.target.value
                : undefined,
            )
          }
          className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
        >
          <option value="">—</option>
          <option value="personal">个人 (Personal)</option>
          <option value="company">公司 (Company)</option>
        </select>
        <p className="text-xs text-muted-foreground">
          Label whether this API key is company-provided or personal.
        </p>
      </div>

      <div className="space-y-2">
        <label htmlFor="provider-apikey" className="text-sm font-medium">
          API Key <span className="text-destructive">*</span>
        </label>
        <div className="flex items-center gap-2">
          <input
            id="provider-apikey"
            type="text"
            value={showApiKey || apiKey.length === 0 ? apiKey : maskApiKey(apiKey)}
            onChange={(e) => setApiKey(e.target.value)}
            onFocus={() => {
              if (!showApiKey && apiKey.length > 0) setShowApiKey(true);
            }}
            placeholder="sk-ant-..."
            readOnly={!showApiKey && apiKey.length > 0}
            className="flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
          />
          <button
            type="button"
            onClick={() => setShowApiKey((s) => !s)}
            className="text-muted-foreground hover:text-foreground transition-colors p-1 shrink-0"
            aria-label={showApiKey ? "Hide API key" : "Show API key"}
          >
            {showApiKey ? <EyeOff className="size-4" /> : <Eye className="size-4" />}
          </button>
          <button
            type="button"
            onClick={handleCopy}
            className="text-muted-foreground hover:text-foreground transition-colors p-1 shrink-0"
            aria-label="Copy API key"
          >
            {copied ? <Check className="size-4 text-green-500" /> : <Copy className="size-4" />}
          </button>
        </div>
        {errors.apiKey !== undefined && <p className="text-xs text-destructive">{errors.apiKey}</p>}
      </div>

      <div className="space-y-2">
        <label className="text-sm font-medium">
          Models <span className="text-destructive">*</span>
        </label>
        {models.map((m, i) => (
          <div
            key={i}
            ref={(el) => {
              modelRowRefs.current[i] = el;
            }}
            className="flex items-center gap-2"
          >
            <div className="relative flex-1">
              <input
                type="text"
                value={m}
                onChange={(e) => {
                  setModels((prev) => {
                    const next = [...prev];
                    next[i] = e.target.value;
                    return next;
                  });
                }}
                placeholder={isMiniMax || isAlibaba ? "Type or select a model..." : "Model name"}
                className="w-full rounded-md border border-input bg-background px-4 py-3 pr-8 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
              />
              {(isMiniMax || isAlibaba) && (
                <>
                  <button
                    type="button"
                    onClick={() => setOpenModelDropdown(openModelDropdown === i ? null : i)}
                    className="absolute right-1 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors p-1 z-10"
                    aria-label="Show model suggestions"
                  >
                    <ChevronDown className="size-4" />
                  </button>
                  {openModelDropdown === i && (
                    <div className="absolute left-0 right-0 top-full mt-1 z-50 bg-popover border border-border rounded-md shadow-md max-h-48 overflow-y-auto">
                      {(isMiniMax ? MINIMAX_MODELS : ALIBABA_MODELS).map((opt) => (
                        <button
                          key={opt}
                          type="button"
                          onClick={() => {
                            setModels((prev) => {
                              const next = [...prev];
                              next[i] = opt;
                              return next;
                            });
                            setOpenModelDropdown(null);
                          }}
                          className="w-full text-left px-3 py-2 text-sm hover:bg-muted transition-colors"
                        >
                          {opt}
                        </button>
                      ))}
                    </div>
                  )}
                </>
              )}
            </div>
            {models.length > 1 && (
              <button
                type="button"
                onClick={() => setModels((prev) => prev.filter((_, idx) => idx !== i))}
                className="text-muted-foreground hover:text-destructive transition-colors p-1 shrink-0"
                aria-label="Remove model"
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="16"
                  height="16"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                >
                  <path d="M3 6h18" />
                  <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
                  <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
                </svg>
              </button>
            )}
          </div>
        ))}
        <button
          type="button"
          onClick={() => setModels((prev) => [...prev, ""])}
          className="text-xs text-primary hover:underline flex items-center gap-1"
        >
          + Add Model
        </button>
        {errors.models !== undefined && <p className="text-xs text-destructive">{errors.models}</p>}
      </div>

      <div className="space-y-2">
        <div className="flex gap-1 border-b border-border">
          <TooltipProvider>
            <Tooltip>
              <TooltipTrigger asChild>
                <button
                  type="button"
                  onClick={() => setActiveTab("anthropic")}
                  className={`px-3 py-2 text-sm font-medium border-b-2 transition-colors ${
                    activeTab === "anthropic"
                      ? "border-primary text-primary"
                      : "border-transparent text-muted-foreground hover:text-foreground"
                  }`}
                >
                  Anthropic Format
                </button>
              </TooltipTrigger>
              <TooltipContent>Anthropic Messages API protocol</TooltipContent>
            </Tooltip>
          </TooltipProvider>
          <TooltipProvider>
            <Tooltip>
              <TooltipTrigger asChild>
                <button
                  type="button"
                  onClick={() => setActiveTab("openai")}
                  className={`px-3 py-2 text-sm font-medium border-b-2 transition-colors ${
                    activeTab === "openai"
                      ? "border-primary text-primary"
                      : "border-transparent text-muted-foreground hover:text-foreground"
                  }`}
                >
                  OpenAI Format
                </button>
              </TooltipTrigger>
              <TooltipContent>OpenAI Chat Completions API protocol</TooltipContent>
            </Tooltip>
          </TooltipProvider>
        </div>
        {errors.format !== undefined && <p className="text-xs text-destructive">{errors.format}</p>}
      </div>

      {activeTab === "anthropic" && (
        <div className="space-y-2">
          <label htmlFor="provider-anthropic-base-url" className="text-sm font-medium">
            Anthropic Base URL
          </label>
          <input
            id="provider-anthropic-base-url"
            type="text"
            value={anthropicBaseUrl}
            onChange={(e) => {
              setManualAnthropicUrlOverride(true);
              setAnthropicBaseUrl(e.target.value);
            }}
            placeholder="https://api.anthropic.com"
            className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
          />
          {errors.anthropicBaseUrl !== undefined && (
            <p className="text-xs text-destructive">{errors.anthropicBaseUrl}</p>
          )}
          <p className="text-xs text-muted-foreground">
            Anthropic-compatible endpoint URL. Leave empty if this provider does not support
            Anthropic format.
          </p>
        </div>
      )}

      {activeTab === "openai" && (
        <div className="space-y-2">
          <label htmlFor="provider-openai-base-url" className="text-sm font-medium">
            OpenAI Base URL
          </label>
          <input
            id="provider-openai-base-url"
            type="text"
            value={openaiBaseUrl}
            onChange={(e) => {
              setManualOpenaiUrlOverride(true);
              setOpenaiBaseUrl(e.target.value);
            }}
            placeholder="https://api.openai.com/v1"
            className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
          />
          {errors.openaiBaseUrl !== undefined && (
            <p className="text-xs text-destructive">{errors.openaiBaseUrl}</p>
          )}
          <p className="text-xs text-muted-foreground">
            OpenAI-compatible endpoint URL. Leave empty if this provider does not support OpenAI
            format.
          </p>
        </div>
      )}

      <div className="space-y-2">
        <label htmlFor="provider-api-docs-url" className="text-sm font-medium">
          API Docs URL
        </label>
        <input
          id="provider-api-docs-url"
          type="text"
          value={apiDocsUrl}
          onChange={(e) => setApiDocsUrl(e.target.value)}
          placeholder="https://api.example.com/docs"
          className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
        />
        <p className="text-xs text-muted-foreground">
          Optional API documentation URL. If not set, uses known provider docs.
        </p>
      </div>

      <div className="sticky bottom-0 bg-card border-t flex gap-2 justify-end pt-2 pb-2">
        <Button type="button" variant="outline" onClick={onCancel} disabled={isSubmitting}>
          Cancel
        </Button>
        <Button type="submit" disabled={isSubmitting}>
          {isSubmitting ? "Saving..." : provider ? "Update Provider" : "Add Provider"}
        </Button>
      </div>
    </form>
  );
}
