import { useEffect, useState } from "react";
import { useParams, Link } from "react-router-dom";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { diffLines } from "diff";
import { ChevronLeft, Star, Download, RotateCcw, Trash2 } from "lucide-react";
import { useCompany } from "@/context/CompanyContext";
import { useBreadcrumbs } from "@/context/BreadcrumbContext";
import { useToast } from "@/context/ToastContext";
import { skillRegistryApi } from "@/api/skillRegistry";
import { queryKeys } from "@/lib/queryKeys";
import { cn, relativeTime } from "@/lib/utils";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import { Tabs, TabsContent } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";
import { PageTabBar } from "@/components/PageTabBar";
import { PageSkeleton } from "@/components/PageSkeleton";
import { EmptyState } from "@/components/EmptyState";
import { StarRating } from "@/components/StarRating";

/* ------------------------------------------------------------------ */
/*  VersionDiff component                                              */
/* ------------------------------------------------------------------ */

function VersionDiff({ oldContent, newContent }: { oldContent: string; newContent: string }) {
  const parts = diffLines(oldContent, newContent);
  return (
    <pre
      role="region"
      aria-label="Version diff"
      className="text-xs font-mono rounded border border-border bg-muted/30 p-4 overflow-x-auto"
    >
      {parts.map((part, i) => (
        <span
          key={i}
          className={cn(
            part.added && "bg-green-500/20 text-green-700 dark:text-green-400",
            part.removed && "bg-red-500/20 text-red-700 dark:text-red-400",
            !part.added && !part.removed && "text-muted-foreground",
          )}
        >
          {part.value}
        </span>
      ))}
    </pre>
  );
}

/* ------------------------------------------------------------------ */
/*  SkillDetail page                                                   */
/* ------------------------------------------------------------------ */

export function SkillDetail() {
  const { skillId: rawSkillId } = useParams<{ skillId: string }>();
  const skillId = rawSkillId ? decodeURIComponent(rawSkillId) : "";

  const { selectedCompany } = useCompany();
  const { setBreadcrumbs } = useBreadcrumbs();
  const { pushToast } = useToast();
  const queryClient = useQueryClient();

  const [detailTab, setDetailTab] = useState("overview");
  const [versionA, setVersionA] = useState<string>("");
  const [versionB, setVersionB] = useState<string>("");

  // Rating form state
  const [pendingStars, setPendingStars] = useState(0);
  const [pendingNote, setPendingNote] = useState("");

  // Install dialog state — used for both install and update flows
  const [installDialog, setInstallDialog] = useState<{
    skillId: string;
    isUpdate: boolean;
    agentSkillsDir?: string;
  } | null>(null);

  // Uninstall confirmation dialog state
  const [uninstallDialog, setUninstallDialog] = useState<{ skillId: string } | null>(null);

  /* ---------------------------------------------------------------- */
  /*  Data queries                                                     */
  /* ---------------------------------------------------------------- */

  const { data: skill, isLoading, isError } = useQuery({
    queryKey: queryKeys.skillRegistry.detail(skillId),
    queryFn: () => skillRegistryApi.getById(skillId),
    enabled: !!skillId,
  });

  const { data: versions = [] } = useQuery({
    queryKey: queryKeys.skillRegistry.versions(skillId),
    queryFn: () => skillRegistryApi.getVersions(skillId),
    enabled: !!skillId,
  });

  const {
    data: ratings = [],
    isLoading: ratingsLoading,
    isError: ratingsError,
  } = useQuery({
    queryKey: ["skill-ratings", skillId],
    queryFn: () => skillRegistryApi.getRatings(skillId),
    enabled: !!skillId,
  });

  /* ---------------------------------------------------------------- */
  /*  Breadcrumbs                                                      */
  /* ---------------------------------------------------------------- */

  useEffect(() => {
    setBreadcrumbs([
      { label: selectedCompany?.name ?? "Workspace", href: "/dashboard" },
      { label: "Skills", href: "../skills" },
      { label: skill?.name ?? "Skill" },
    ]);
  }, [selectedCompany?.name, skill?.name, setBreadcrumbs]);

  /* ---------------------------------------------------------------- */
  /*  Mutations                                                        */
  /* ---------------------------------------------------------------- */

  const invalidateSkill = () => {
    queryClient.invalidateQueries({ queryKey: queryKeys.skillRegistry.detail(skillId) });
    queryClient.invalidateQueries({ queryKey: queryKeys.skillRegistry.list });
  };

  const installMutation = useMutation({
    mutationFn: ({ agentSkillsDir }: { agentSkillsDir: string }) =>
      skillRegistryApi.install(skillId, agentSkillsDir),
    onSuccess: () => {
      invalidateSkill();
      setInstallDialog(null);
      pushToast({ title: "Skill installed", tone: "success" });
    },
    onError: (err: Error) => {
      pushToast({ title: "Install failed", body: err.message, tone: "error" });
    },
  });

  const updateMutation = useMutation({
    mutationFn: ({ agentSkillsDir }: { agentSkillsDir: string }) =>
      skillRegistryApi.install(skillId, agentSkillsDir),
    onSuccess: () => {
      invalidateSkill();
      setInstallDialog(null);
      pushToast({ title: "Skill updated", tone: "success" });
    },
    onError: (err: Error) => {
      pushToast({ title: "Update failed", body: err.message, tone: "error" });
    },
  });

  const rollbackMutation = useMutation({
    mutationFn: ({ versionId, agentSkillsDir }: { versionId: string; agentSkillsDir: string }) =>
      skillRegistryApi.rollback(skillId, versionId, agentSkillsDir),
    onSuccess: () => {
      invalidateSkill();
      pushToast({ title: "Rolled back to previous version", tone: "success" });
    },
    onError: (err: Error) => {
      pushToast({ title: "Rollback failed", body: err.message, tone: "error" });
    },
  });

  const removeMutation = useMutation({
    mutationFn: () => skillRegistryApi.remove(skillId),
    onSuccess: () => {
      invalidateSkill();
      setUninstallDialog(null);
      pushToast({ title: "Skill uninstalled", tone: "success" });
    },
    onError: (err: Error) => {
      pushToast({ title: "Uninstall failed", body: err.message, tone: "error" });
    },
  });

  const saveRatingMutation = useMutation({
    mutationFn: ({ stars, note }: { stars: number; note: string }) =>
      skillRegistryApi.addRating(skillId, {
        stars,
        versionId: skill?.activeVersionId ?? undefined,
        note: note.trim() || undefined,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["skill-ratings", skillId] });
      setPendingStars(0);
      setPendingNote("");
      pushToast({ title: "Rating saved", tone: "success" });
    },
    onError: (err: Error) => {
      pushToast({ title: "Failed to save rating", body: err.message, tone: "error" });
    },
  });

  /* ---------------------------------------------------------------- */
  /*  Loading / error states                                           */
  /* ---------------------------------------------------------------- */

  if (isLoading) {
    return (
      <main className="flex-1 overflow-y-auto p-6 space-y-4">
        <PageSkeleton variant="detail" />
      </main>
    );
  }

  if (isError) {
    return (
      <main className="flex-1 overflow-y-auto p-6 space-y-4">
        <p className="text-sm text-destructive">
          Failed to load skills. Check that the skill registry backend is running and try again.
        </p>
      </main>
    );
  }

  if (!skill) {
    return (
      <main className="flex-1 overflow-y-auto p-6 space-y-4">
        <p className="text-sm text-muted-foreground">Skill not found.</p>
      </main>
    );
  }

  const isInstalled = !!skill.activeVersionId;
  const isMutating =
    installMutation.isPending ||
    updateMutation.isPending ||
    rollbackMutation.isPending ||
    removeMutation.isPending;

  /* ---------------------------------------------------------------- */
  /*  Render                                                           */
  /* ---------------------------------------------------------------- */

  return (
    <main className="flex-1 overflow-y-auto p-6 space-y-4">
      {/* Back link */}
      <Link
        to="../skills"
        className="text-sm text-muted-foreground hover:underline flex items-center gap-1"
      >
        <ChevronLeft className="h-4 w-4" /> Skills
      </Link>

      {/* Header */}
      <div className="flex items-start justify-between gap-4">
        <div>
          <h1 className="text-xl font-semibold">{skill.name}</h1>
          <Badge variant="secondary" className="text-xs mt-1">
            {skill.sourceId}
          </Badge>
        </div>
        <div className="flex gap-2 flex-shrink-0">
          {!isInstalled && (
            <Button
              size="sm"
              variant="outline"
              disabled={isMutating}
              onClick={() => setInstallDialog({ skillId, isUpdate: false })}
            >
              <Download className="h-3.5 w-3.5 mr-1" />
              Install skill
            </Button>
          )}
          {isInstalled && (
            <>
              <Button
                size="sm"
                variant="outline"
                disabled={isMutating}
                onClick={() => setInstallDialog({ skillId, isUpdate: true })}
              >
                Update skill
              </Button>
              <Button
                size="sm"
                variant="destructive"
                disabled={isMutating}
                onClick={() => setUninstallDialog({ skillId })}
              >
                <Trash2 className="h-3.5 w-3.5 mr-1" />
                Uninstall
              </Button>
            </>
          )}
        </div>
      </div>

      {/* Description */}
      {skill.description && (
        <p className="text-sm text-muted-foreground">{skill.description}</p>
      )}

      {/* Detail tabs */}
      <TooltipProvider>
        <Tabs value={detailTab} onValueChange={setDetailTab}>
          <PageTabBar
            items={[
              { value: "overview", label: "Overview" },
              { value: "versions", label: "Versions" },
              { value: "diff", label: "Diff" },
              { value: "ratings", label: "Ratings" },
            ]}
            value={detailTab}
            onValueChange={setDetailTab}
            align="start"
          />

          {/* Overview tab */}
          <TabsContent value="overview" className="space-y-1 pt-4">
            <div className="space-y-1">
              <div className="flex items-center justify-between py-2">
                <span className="text-xs text-muted-foreground">Installs</span>
                <span className="text-sm font-semibold">{skill.ratingCount ?? "\u2014"}</span>
              </div>
              <div className="flex items-center justify-between py-2">
                <span className="text-xs text-muted-foreground">Average rating</span>
                <span className="flex items-center gap-1 text-sm font-semibold">
                  {skill.averageRating != null ? (
                    <>
                      <Star className="h-3.5 w-3.5 fill-amber-400 text-amber-400" />
                      {skill.averageRating.toFixed(1)}
                    </>
                  ) : (
                    "No ratings yet"
                  )}
                </span>
              </div>
              {skill.averageRating != null && skill.ratingCount != null && (
                <div className="flex items-center justify-between py-2">
                  <span className="text-xs text-muted-foreground">Community</span>
                  <span className="text-sm font-semibold">({skill.ratingCount} ratings)</span>
                </div>
              )}
              <div className="flex items-center justify-between py-2">
                <span className="text-xs text-muted-foreground">Source</span>
                <span className="text-xs font-mono text-muted-foreground">{skill.sourceId}</span>
              </div>
              <div className="flex items-center justify-between py-2">
                <span className="text-xs text-muted-foreground">Active version</span>
                <span className="text-xs font-mono text-muted-foreground">
                  {skill.activeVersionId
                    ? `v${skill.activeVersionId.split("@").pop() ?? skill.activeVersionId}`
                    : "\u2014"}
                </span>
              </div>
              {/* Usage stats — Phase 12 */}
              {skill.taskCount != null && skill.taskCount > 0 && (
                <div className="flex items-center justify-between py-2">
                  <span className="text-xs text-muted-foreground">Tasks completed</span>
                  <span className="text-sm font-semibold">{skill.taskCount}</span>
                </div>
              )}
              {skill.avgCostUsd != null && (
                <div className="flex items-center justify-between py-2">
                  <span className="text-xs text-muted-foreground">Avg task cost</span>
                  <span className="text-sm font-semibold">${skill.avgCostUsd.toFixed(4)}</span>
                </div>
              )}
              {skill.lastUsedAt != null && (
                <div className="flex items-center justify-between py-2">
                  <span className="text-xs text-muted-foreground">Last used</span>
                  <span className="text-sm font-semibold">{relativeTime(new Date(skill.lastUsedAt))}</span>
                </div>
              )}
            </div>
          </TabsContent>

          {/* Versions tab */}
          <TabsContent value="versions" className="pt-4">
            {versions.length === 0 ? (
              <p className="text-sm text-muted-foreground">No versions fetched yet.</p>
            ) : (
              <ScrollArea className="max-h-96">
                <div className="space-y-1">
                  {versions.map((v) => (
                    <div
                      key={v.id}
                      className="flex items-center justify-between py-2 px-2 rounded hover:bg-accent/50"
                    >
                      <div>
                        <span className="text-xs font-mono text-muted-foreground">{v.version}</span>
                        <span className="text-xs text-muted-foreground ml-2">
                          {relativeTime(new Date(v.fetchedAt))}
                        </span>
                      </div>
                      {v.id === skill.activeVersionId && (
                        <Badge variant="outline" className="text-xs">
                          Active
                        </Badge>
                      )}
                    </div>
                  ))}
                </div>
              </ScrollArea>
            )}
          </TabsContent>

          {/* Diff tab */}
          <TabsContent value="diff" className="pt-4 space-y-4">
            <div className="flex gap-2 mb-4">
              <Select value={versionA} onValueChange={setVersionA}>
                <SelectTrigger className="w-48">
                  <SelectValue placeholder="Select version A" />
                </SelectTrigger>
                <SelectContent>
                  {versions.map((v) => (
                    <SelectItem key={v.id} value={v.id}>
                      {v.version}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <Select value={versionB} onValueChange={setVersionB}>
                <SelectTrigger className="w-48">
                  <SelectValue placeholder="Select version B" />
                </SelectTrigger>
                <SelectContent>
                  {versions.map((v) => (
                    <SelectItem key={v.id} value={v.id}>
                      {v.version}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            {versionA && versionB ? (
              <div className="space-y-2">
                <p className="text-xs text-muted-foreground">
                  Version diff requires file content endpoint (coming in a future update).
                </p>
                <VersionDiff oldContent="" newContent="" />
              </div>
            ) : (
              <p className="text-xs text-muted-foreground">
                Select two versions above to compare them.
              </p>
            )}
          </TabsContent>

          {/* Ratings tab */}
          <TabsContent value="ratings" className="pt-4 space-y-6">
            {/* Section 1: Rate this skill */}
            <div className="space-y-4">
              <h2 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
                Rate this skill
              </h2>
              <div className="space-y-2">
                <StarRating value={pendingStars} onChange={setPendingStars} size="md" />
                <Textarea
                  placeholder="Add a note about this version\u2026"
                  value={pendingNote}
                  onChange={(e) => setPendingNote(e.target.value)}
                  rows={3}
                  className="resize-none"
                />
              </div>
              <Button
                size="sm"
                variant="default"
                disabled={pendingStars === 0 || saveRatingMutation.isPending}
                onClick={() => {
                  if (pendingStars === 0) return;
                  saveRatingMutation.mutate({ stars: pendingStars, note: pendingNote });
                }}
              >
                {saveRatingMutation.isPending ? "Saving\u2026" : "Save rating"}
              </Button>
              {saveRatingMutation.isError && (
                <p className="text-sm text-destructive">
                  {(saveRatingMutation.error as Error).message}
                </p>
              )}
            </div>

            <Separator />

            {/* Section 2: Your Rating History */}
            <div className="space-y-3">
              <h2 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
                Your Rating History
              </h2>
              {ratingsError && (
                <p className="text-sm text-destructive">Failed to load ratings.</p>
              )}
              {ratingsLoading && (
                <div aria-hidden="true" className="space-y-2">
                  <Skeleton className="h-8 w-full" />
                  <Skeleton className="h-8 w-full" />
                  <Skeleton className="h-8 w-full" />
                </div>
              )}
              {!ratingsLoading && !ratingsError && ratings.length === 0 && (
                <EmptyState
                  icon={Star}
                  message="No ratings yet"
                />
              )}
              {!ratingsLoading && !ratingsError && ratings.length > 0 && (
                <ScrollArea className="max-h-80">
                  <div className="space-y-1">
                    {ratings.map((r) => (
                      <div
                        key={r.id}
                        className="flex items-start justify-between py-2 px-2 rounded hover:bg-accent/50"
                      >
                        <div className="space-y-1">
                          <div className="flex items-center gap-2">
                            <StarRating value={r.stars} readonly size="sm" />
                            {r.versionId && (
                              <Badge variant="outline" className="text-xs font-mono">
                                {r.versionId.slice(-7)}
                              </Badge>
                            )}
                          </div>
                          {r.note && (
                            <p className="text-sm text-muted-foreground">{r.note}</p>
                          )}
                        </div>
                        <span className="text-xs text-muted-foreground shrink-0 ml-4">
                          {relativeTime(new Date(r.createdAt))}
                        </span>
                      </div>
                    ))}
                  </div>
                </ScrollArea>
              )}
            </div>

            <Separator />

            {/* Section 3: Community Ratings */}
            <div className="space-y-3">
              <h2 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
                Community Ratings
              </h2>
              {skill.averageRating != null ? (
                <div className="space-y-1">
                  <div className="flex items-center justify-between py-2">
                    <span className="text-xs text-muted-foreground">Average</span>
                    <span className="flex items-center gap-2">
                      <StarRating value={Math.round(skill.averageRating)} readonly size="sm" />
                      <span className="text-sm font-semibold">{skill.averageRating.toFixed(1)}</span>
                    </span>
                  </div>
                  <div className="flex items-center justify-between py-2">
                    <span className="text-xs text-muted-foreground">Ratings</span>
                    <span className="text-sm font-semibold">{skill.ratingCount}</span>
                  </div>
                </div>
              ) : (
                <p className="text-sm text-muted-foreground">No community ratings available.</p>
              )}
            </div>
          </TabsContent>
        </Tabs>
      </TooltipProvider>

      {/* Install / Update dialog */}
      <Dialog open={!!installDialog} onOpenChange={(open) => !open && setInstallDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>
              {installDialog?.isUpdate ? "Update skill" : "Install skill"}
            </DialogTitle>
            <DialogDescription>
              {installDialog?.isUpdate
                ? "Update this skill to the latest version for your agents."
                : "Install this skill to add new capabilities to your agents."}
            </DialogDescription>
          </DialogHeader>
          <div className="py-2">
            <p className="text-sm text-muted-foreground">
              Agent skills directory is required to install. Enter the path to the agent&apos;s
              skills directory.
            </p>
            <input
              type="text"
              className="mt-2 w-full rounded-md border border-border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-ring"
              placeholder="/path/to/agent/skills"
              value={installDialog?.agentSkillsDir ?? ""}
              onChange={(e) =>
                setInstallDialog((d) => d ? { ...d, agentSkillsDir: e.target.value } : null)
              }
            />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setInstallDialog(null)}>
              Cancel
            </Button>
            <Button
              disabled={!installDialog?.agentSkillsDir || isMutating}
              onClick={() => {
                if (!installDialog?.agentSkillsDir) return;
                if (installDialog.isUpdate) {
                  updateMutation.mutate({ agentSkillsDir: installDialog.agentSkillsDir });
                } else {
                  installMutation.mutate({ agentSkillsDir: installDialog.agentSkillsDir });
                }
              }}
            >
              {installDialog?.isUpdate
                ? updateMutation.isPending
                  ? "Updating\u2026"
                  : "Update skill"
                : installMutation.isPending
                  ? "Installing\u2026"
                  : "Install skill"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Uninstall confirmation dialog */}
      <Dialog open={!!uninstallDialog} onOpenChange={(open) => !open && setUninstallDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Uninstall skill?</DialogTitle>
            <DialogDescription>
              This will remove the skill files from the agent&apos;s directory. You can reinstall
              it later.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setUninstallDialog(null)}>
              Keep skill
            </Button>
            <Button
              variant="destructive"
              disabled={removeMutation.isPending}
              onClick={() => removeMutation.mutate()}
            >
              {removeMutation.isPending ? "Uninstalling\u2026" : "Yes, uninstall"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </main>
  );
}
