import { useState, useEffect } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { trpc } from "@/lib/trpc";
import { toast } from "sonner";
import { Loader2, Plus, Wand2, Sparkles } from "lucide-react";

interface AgentCreateModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSuccess?: () => void;
}

const AGENT_ROLES = [
  { value: "developer", label: "Developer — Code generation & testing" },
  { value: "researcher", label: "Researcher — Data analysis & research" },
  { value: "executor", label: "Executor — Task automation" },
  { value: "monitor", label: "Monitor — System monitoring" },
  { value: "analyst", label: "Analyst — Data processing & reports" },
  { value: "writer", label: "Writer — Content generation" },
  { value: "coordinator", label: "Coordinator — Multi-agent orchestration" },
];

const DEFAULT_FORM = {
  name: "",
  description: "",
  role: "developer",
  provider: "",
  model: "",
  temperature: 0.7,
  maxTokens: 2048,
  systemPrompt: "",
};

function toNum(v: string | number | null | undefined, fallback = 0): number {
  if (v === null || v === undefined) return fallback;
  const n = typeof v === "string" ? parseFloat(v) : v;
  return isNaN(n) ? fallback : n;
}

export function AgentCreateModal({ open, onOpenChange, onSuccess }: AgentCreateModalProps) {
  const [formData, setFormData] = useState({ ...DEFAULT_FORM });
  const [isLoading, setIsLoading] = useState(false);
  const [isAutoFilling, setIsAutoFilling] = useState(false);
  const [maxTokensHint, setMaxTokensHint] = useState<number | null>(null);
  const [modelInfoLoading, setModelInfoLoading] = useState(false);

  // ─── Remote data ───────────────────────────────────────────────────────────

  const { data: modelsData, isLoading: modelsLoading } = trpc.ollama.models.useQuery(undefined, {
    staleTime: 60_000,
  });
  const { data: configData } = trpc.config.providers.useQuery(undefined, {
    staleTime: 300_000,
  });
  const connectedProviders = configData?.providers ?? [];

  // ─── Model info (context_length) ───────────────────────────────────────────
  const { data: modelInfoData, isFetching: modelInfoFetching } = trpc.ollama.modelInfo.useQuery(
    { modelId: formData.model },
    {
      enabled: !!formData.model,
      staleTime: 300_000,
    }
  );

  // When model info arrives, update maxTokens with context_length
  useEffect(() => {
    if (modelInfoData?.contextLength && modelInfoData.contextLength > 0) {
      setMaxTokensHint(modelInfoData.contextLength);
      setFormData((prev) => ({ ...prev, maxTokens: modelInfoData.contextLength }));
    }
  }, [modelInfoData]);

  // Auto-select first provider when providers load
  useEffect(() => {
    if (connectedProviders.length > 0 && !formData.provider) {
      setFormData((prev) => ({ ...prev, provider: connectedProviders[0].name }));
    }
  }, [connectedProviders]);

  // Auto-select first model when models load
  useEffect(() => {
    const availableModels: string[] = modelsData?.models?.map((m: any) => m.id || m) ?? [];
    if (availableModels.length > 0 && !formData.model) {
      setFormData((prev) => ({ ...prev, model: availableModels[0] }));
    }
  }, [modelsData]);

  // ─── Mutations ─────────────────────────────────────────────────────────────

  const createMutation = trpc.agents.create.useMutation({
    onSuccess: () => {
      toast.success("Agent created successfully");
      setFormData({ ...DEFAULT_FORM });
      onOpenChange(false);
      onSuccess?.();
    },
    onError: (error) => {
      toast.error(`Failed to create agent: ${error.message}`);
    },
  });

  const compileMutation = trpc.agentCompiler.compile.useMutation({
    onSuccess: (result) => {
      if (!result.success || !result.config) {
        toast.error("AI auto-fill failed — fill fields manually");
        setIsAutoFilling(false);
        return;
      }
      const cfg = result.config;
      setFormData((prev) => ({
        ...prev,
        role: cfg.role || prev.role,
        provider: cfg.provider || prev.provider,
        model: cfg.model || prev.model,
        temperature: toNum(cfg.temperature, 0.7),
        maxTokens: cfg.maxTokens || prev.maxTokens,
        systemPrompt: cfg.systemPrompt || prev.systemPrompt,
      }));
      toast.success("AI filled the fields — review and save");
      setIsAutoFilling(false);
    },
    onError: (err) => {
      toast.error(`Auto-fill error: ${err.message}`);
      setIsAutoFilling(false);
    },
  });

  // ─── Handlers ──────────────────────────────────────────────────────────────

  const handleCreate = async () => {
    if (!formData.name.trim()) {
      toast.error("Agent name is required");
      return;
    }
    setIsLoading(true);
    try {
      await createMutation.mutateAsync({
        name: formData.name,
        description: formData.description,
        role: formData.role,
        provider: formData.provider || "Ollama",
        model: formData.model,
        temperature: formData.temperature,
        maxTokens: formData.maxTokens,
        systemPrompt: formData.systemPrompt,
        allowedTools: [],
      });
    } finally {
      setIsLoading(false);
    }
  };

  const handleAutoFill = async () => {
    if (!formData.name.trim()) {
      toast.error("Enter Agent Name first — the AI needs it to suggest parameters");
      return;
    }
    setIsAutoFilling(true);
    const spec = `Agent name: ${formData.name}\n${formData.description ? `Description: ${formData.description}` : ""}`.trim();
    await compileMutation.mutateAsync({
      specification: spec,
      name: formData.name,
      preferredProvider: formData.provider || undefined,
      preferredModel: formData.model || undefined,
    });
  };

  const handleModelChange = (model: string) => {
    setFormData((prev) => ({ ...prev, model }));
    setMaxTokensHint(null);
  };

  // ─── Derived ───────────────────────────────────────────────────────────────
  const availableModels: string[] = modelsData?.models?.map((m: any) => m.id || m) ?? [];
  const canAutoFill = formData.name.trim().length > 0;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto bg-card border-border">
        <DialogHeader>
          <DialogTitle className="font-mono text-primary flex items-center gap-2">
            <Plus className="w-4 h-4" />
            Deploy New Agent
          </DialogTitle>
        </DialogHeader>

        <div className="space-y-4">
          {/* ── Name + Description ─────────────────────────────────────────── */}
          <div className="grid grid-cols-[1fr_auto] gap-2 items-end">
            <div className="space-y-1.5">
              <Label className="text-xs text-muted-foreground font-mono">AGENT NAME *</Label>
              <Input
                placeholder="e.g. Code Reviewer Agent"
                value={formData.name}
                onChange={(e) => setFormData({ ...formData, name: e.target.value })}
                className="font-mono"
              />
            </div>
            {/* Magic wand — auto-fill remaining fields via AI */}
            <Button
              variant="outline"
              size="sm"
              onClick={handleAutoFill}
              disabled={!canAutoFill || isAutoFilling}
              className={`h-9 gap-1.5 border-primary/40 text-primary hover:bg-primary/10 transition-all ${
                canAutoFill ? "opacity-100" : "opacity-40"
              }`}
              title="Auto-fill fields with AI based on name & description"
            >
              {isAutoFilling ? (
                <Loader2 className="w-4 h-4 animate-spin" />
              ) : (
                <Wand2 className="w-4 h-4" />
              )}
              <span className="text-xs font-mono hidden sm:inline">
                {isAutoFilling ? "Thinking..." : "Auto-fill"}
              </span>
            </Button>
          </div>

          {canAutoFill && !isAutoFilling && (
            <p className="text-[11px] text-muted-foreground font-mono -mt-2 flex items-center gap-1">
              <Sparkles className="w-3 h-3 text-primary" />
              Click <span className="text-primary">Auto-fill</span> to let AI suggest temperature, system prompt and other params
            </p>
          )}

          <div className="space-y-1.5">
            <Label className="text-xs text-muted-foreground font-mono">DESCRIPTION</Label>
            <Textarea
              placeholder="What is this agent responsible for?"
              value={formData.description}
              onChange={(e) => setFormData({ ...formData, description: e.target.value })}
              rows={2}
              className="font-mono text-sm resize-none"
            />
          </div>

          {/* ── Role ───────────────────────────────────────────────────────── */}
          <div className="space-y-1.5">
            <Label className="text-xs text-muted-foreground font-mono">ROLE *</Label>
            <Select value={formData.role} onValueChange={(v) => setFormData({ ...formData, role: v })}>
              <SelectTrigger className="font-mono">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {AGENT_ROLES.map((role) => (
                  <SelectItem key={role.value} value={role.value} className="font-mono text-sm">
                    {role.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* ── Provider + Model side-by-side ──────────────────────────────── */}
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-1.5">
              <Label className="text-xs text-muted-foreground font-mono">PROVIDER *</Label>
              <Select
                value={formData.provider}
                onValueChange={(v) => setFormData({ ...formData, provider: v, model: "" })}
              >
                <SelectTrigger className="font-mono w-full truncate">
                  <SelectValue placeholder="Select provider..." />
                </SelectTrigger>
                <SelectContent>
                  {connectedProviders.length > 0 ? (
                    connectedProviders.map((p) => (
                      <SelectItem key={p.id} value={p.name} className="font-mono text-sm">
                        <span className="flex items-center gap-2">
                          {p.name}
                          <span className="text-[10px] text-neon-green font-mono">● connected</span>
                        </span>
                      </SelectItem>
                    ))
                  ) : (
                    <SelectItem value="Ollama" className="font-mono text-sm">
                      Ollama
                    </SelectItem>
                  )}
                </SelectContent>
              </Select>
            </div>

            <div className="space-y-1.5">
              <Label className="text-xs text-muted-foreground font-mono flex items-center gap-2">
                MODEL *
                {modelsLoading && <Loader2 className="w-3 h-3 animate-spin text-primary" />}
                {!modelsLoading && availableModels.length > 0 && (
                  <span className="text-[10px] text-neon-green font-normal">{availableModels.length} available</span>
                )}
                {!modelsLoading && availableModels.length === 0 && (
                  <span className="text-[10px] text-neon-amber font-normal">API unavailable</span>
                )}
              </Label>
              <Select
                value={formData.model}
                onValueChange={handleModelChange}
                disabled={modelsLoading}
              >
                <SelectTrigger className="font-mono w-full truncate">
                  <SelectValue placeholder={modelsLoading ? "Loading models..." : "Select model..."} />
                </SelectTrigger>
                <SelectContent>
                  {availableModels.length > 0 ? (
                    availableModels.map((model: string) => (
                      <SelectItem key={model} value={model} className="font-mono text-sm">
                        {model}
                      </SelectItem>
                    ))
                  ) : (
                    <SelectItem value="_placeholder" disabled className="font-mono text-sm">
                      {modelsLoading ? "Loading..." : "No models available"}
                    </SelectItem>
                  )}
                </SelectContent>
              </Select>
            </div>
          </div>

          {/* ── Temperature + Max Tokens ────────────────────────────────────── */}
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <div className="flex justify-between items-center">
                <Label className="text-xs text-muted-foreground font-mono">TEMPERATURE</Label>
                <span className="text-xs font-mono text-primary">{formData.temperature.toFixed(2)}</span>
              </div>
              <input
                type="range"
                min="0"
                max="2"
                step="0.01"
                value={formData.temperature}
                onChange={(e) => setFormData({ ...formData, temperature: parseFloat(e.target.value) })}
                className="w-full accent-cyan-400 cursor-pointer"
              />
              <div className="flex justify-between text-[10px] text-muted-foreground font-mono">
                <span>0.0 precise</span>
                <span>2.0 creative</span>
              </div>
            </div>

            <div className="space-y-1.5">
              <Label className="text-xs text-muted-foreground font-mono flex items-center gap-1.5">
                MAX TOKENS
                {(modelInfoFetching) && (
                  <Loader2 className="w-3 h-3 animate-spin text-primary" />
                )}
                {maxTokensHint && maxTokensHint > 0 && !modelInfoFetching && (
                  <span className="text-[10px] text-neon-green font-normal">
                    max {maxTokensHint.toLocaleString()} from API
                  </span>
                )}
              </Label>
              <Input
                type="number"
                value={formData.maxTokens}
                onChange={(e) => setFormData({ ...formData, maxTokens: parseInt(e.target.value) || 2048 })}
                className="font-mono"
                min={1}
                max={maxTokensHint || 1000000}
              />
              {maxTokensHint && maxTokensHint > 0 && (
                <p className="text-[10px] text-muted-foreground font-mono">
                  Context window: {maxTokensHint.toLocaleString()} tokens
                </p>
              )}
            </div>
          </div>

          {/* ── System Prompt ───────────────────────────────────────────────── */}
          <div className="space-y-1.5">
            <Label className="text-xs text-muted-foreground font-mono">SYSTEM PROMPT</Label>
            <Textarea
              placeholder="Define the agent's behavior and instructions... (AI auto-fill will suggest this)"
              value={formData.systemPrompt}
              onChange={(e) => setFormData({ ...formData, systemPrompt: e.target.value })}
              rows={4}
              className="font-mono text-sm resize-none"
            />
          </div>
        </div>

        <DialogFooter className="gap-2">
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            onClick={handleCreate}
            disabled={isLoading || createMutation.isPending || !formData.name.trim()}
            className="bg-primary/15 text-primary border border-primary/30 hover:bg-primary/25"
          >
            {isLoading || createMutation.isPending ? (
              <>
                <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                Creating...
              </>
            ) : (
              <>
                <Plus className="w-4 h-4 mr-2" />
                Create Agent
              </>
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
