import { useParams } from "react-router";
import { NavLink, Outlet, Navigate } from "react-router";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { client } from "@/client";
import { Lock, Globe, Archive, GitFork, Star, Eye, EyeOff } from "lucide-react";
import { cn } from "@/lib/utils";

export function RepoIndexRedirect() {
  const { projectName = "", repoName = "" } = useParams();
  const { data: readme } = useQuery({
    queryKey: ["repo", projectName, repoName, "readme"],
    queryFn: async () => {
      const res = await client.gitGetReadme(projectName, repoName);
      return res.data;
    },
    enabled: Boolean(projectName) && Boolean(repoName),
    retry: false,
  });

  if (readme?.html) return <Navigate replace to="readme" />;
  return <Navigate replace to="code" />;
}

function formatSize(bytes: number) {
  if (bytes === 0) return "Empty";
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

function formatDate(date: string) {
  const now = new Date();
  const d = new Date(date);
  const diff = now.getTime() - d.getTime();
  const days = Math.floor(diff / 86400000);
  if (days < 1) return "today";
  if (days === 1) return "1 day ago";
  if (days < 30) return `${days} days ago`;
  if (days < 365) return `${Math.floor(days / 30)}mo ago`;
  return `${Math.floor(days / 365)}y ago`;
}

const tabs = [
  { label: "Code", to: "code" },
  { label: "Commits", to: "commits" },
  { label: "Branches", to: "branches" },
  { label: "Tags", to: "tags" },
  { label: "Pull Requests", to: "pulls" },
  { label: "Contributors", to: "contributors" },
  { label: "Webhooks", to: "webhooks" },
  { label: "Settings", to: "settings" },
];

export default function RepoLayout() {
  const { projectName = "", repoName = "" } = useParams();
  const qc = useQueryClient();

  const { data: repo, isLoading } = useQuery({
    queryKey: ["repo", projectName, repoName],
    queryFn: async () => {
      const res = await client.gitGetRepo(projectName, repoName);
      return res.data;
    },
    enabled: Boolean(projectName) && Boolean(repoName),
    retry: false,
  });

  const { data: starData } = useQuery({
    queryKey: ["repo", projectName, repoName, "star"],
    queryFn: async () => {
      const res: any = await client.gitStarStatus(projectName, repoName);
      return res.data as { starred: boolean; count: number };
    },
    enabled: Boolean(projectName) && Boolean(repoName),
    retry: false,
  });

  const starRepo = useMutation({
    mutationFn: async () => {
      if (starData?.starred) { await client.gitUnstarRepo(projectName, repoName); }
      else { await client.gitStarRepo(projectName, repoName); }
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["repo", projectName, repoName, "star"] }),
  });

  const { data: watchData } = useQuery({
    queryKey: ["repo", projectName, repoName, "watch"],
    queryFn: async () => {
      const res: any = await client.gitWatchStatus(projectName, repoName);
      return res.data as { watching: boolean; count: number };
    },
    enabled: Boolean(projectName) && Boolean(repoName),
    retry: false,
  });

  const watchRepo = useMutation({
    mutationFn: async () => {
      if (watchData?.watching) { await client.gitUnwatchRepo(projectName, repoName); }
      else { await client.gitWatchRepo(projectName, repoName, {} as any); }
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["repo", projectName, repoName, "watch"] }),
  });

  const { data: readme } = useQuery({
    queryKey: ["repo", projectName, repoName, "readme"],
    queryFn: async () => {
      const res = await client.gitGetReadme(projectName, repoName);
      return res.data;
    },
    enabled: Boolean(projectName) && Boolean(repoName),
    retry: false,
  });

  const allTabs = [
    ...(readme?.html ? [{ label: "README", to: "readme" }] : []),
    ...tabs,
  ];

  if (isLoading) {
    return (
      <div className="px-8 py-10 space-y-3">
        <div className="h-7 animate-pulse rounded bg-muted/50 w-64" />
        <div className="h-5 animate-pulse rounded bg-muted/50 w-80" />
        <div className="h-4 animate-pulse rounded bg-muted/50 w-48" />
      </div>
    );
  }

  if (!repo) {
    return (
      <div className="flex flex-col items-center justify-center px-8 py-20 text-center">
        <div className="grid size-16 place-items-center rounded-2xl bg-muted/40">
          <GitFork className="size-7 text-muted-foreground/40" />
        </div>
        <h2 className="mt-5 font-heading text-lg font-semibold text-foreground">Repository not found</h2>
        <p className="mt-2 max-w-sm text-[13px] text-muted-foreground">
          This repository doesn't exist or you don't have permission to view it.
        </p>
      </div>
    );
  }

  return (
    <div className="mx-auto max-w-6xl px-6 py-8 lg:px-8 lg:py-10">
      {/* Header */}
      <div className="flex items-center gap-2 flex-wrap">
        <h1 className="font-heading text-lg font-bold text-foreground">{repo.name}</h1>
        {repo.visibility === "private" ? (
          <span className="inline-flex items-center gap-1 rounded-md border border-border bg-muted/30 px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
            <Lock className="size-3" />Private
          </span>
        ) : (
          <span className="inline-flex items-center gap-1 rounded-md border border-border bg-muted/30 px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
            <Globe className="size-3" />Public
          </span>
        )}
        {repo.is_archived && (
          <span className="inline-flex items-center gap-1 rounded-md border border-border bg-muted/30 px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
            <Archive className="size-3" />Archived
          </span>
        )}
        {repo.is_mirror && (
          <span className="inline-flex items-center gap-1 rounded-md border border-border bg-muted/30 px-2 py-0.5 text-[11px] font-medium text-muted-foreground">Mirror</span>
        )}
        {repo.is_template && (
          <span className="inline-flex items-center gap-1 rounded-md border border-border bg-muted/30 px-2 py-0.5 text-[11px] font-medium text-muted-foreground">Template</span>
        )}
      </div>

      {repo.description && (
        <p className="mt-1 text-[13px] text-muted-foreground max-w-2xl">{repo.description}</p>
      )}

      <div className="mt-3 flex items-center gap-3 text-[12px] text-muted-foreground flex-wrap">
        <span><span className="text-foreground/60">default branch:</span> {repo.default_branch}</span>
        <span className="text-muted-foreground/30">|</span>
        <span>{formatSize(repo.size_bytes)}</span>
        <span className="text-muted-foreground/30">|</span>
        <span>created {formatDate(repo.created_at)}</span>
        <div className="flex items-center gap-1.5 ml-2">
          <button
            className={cn("inline-flex h-8 items-center gap-1.5 rounded-lg border px-3 text-[12px] font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30", starData?.starred ? "border-primary/30 bg-primary/10 text-primary" : "border-border bg-card text-muted-foreground hover:bg-muted/50 hover:text-foreground")}
            disabled={starRepo.isPending}
            onClick={() => starRepo.mutate()}
          >
            <Star className={cn("size-3", starData?.starred && "fill-primary")} />
            {starData?.starred ? "Starred" : "Star"}
            {typeof starData?.count === "number" && <span className="text-[11px] tabular-nums opacity-70">{starData.count}</span>}
          </button>
          <button
            className={cn("inline-flex h-8 items-center gap-1.5 rounded-lg border px-3 text-[12px] font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30", watchData?.watching ? "border-primary/30 bg-primary/10 text-primary" : "border-border bg-card text-muted-foreground hover:bg-muted/50 hover:text-foreground")}
            disabled={watchRepo.isPending}
            onClick={() => watchRepo.mutate()}
          >
            {watchData?.watching ? <Eye className="size-3" /> : <EyeOff className="size-3" />}
            {watchData?.watching ? "Watching" : "Watch"}
            {typeof watchData?.count === "number" && <span className="text-[11px] tabular-nums opacity-70">{watchData.count}</span>}
          </button>
        </div>
      </div>

      {/* Tab nav */}
      <nav className="mt-6 flex items-center gap-1 overflow-x-auto rounded-xl border border-border bg-muted/30 p-1">
        {allTabs.map((tab) => (
          <NavLink
            className={({ isActive }) => cn(
              "inline-flex h-8 shrink-0 items-center rounded-lg px-3 text-[13px] font-medium transition-colors",
              isActive ? "bg-card text-foreground shadow-sm ring-1 ring-border" : "text-muted-foreground hover:bg-background/60 hover:text-foreground",
            )}
            end
            key={tab.to}
            to={tab.to}
          >
            {tab.label}
          </NavLink>
        ))}
      </nav>

      {/* Content */}
      <div className="mt-6">
        <Outlet />
      </div>
    </div>
  );
}
