import { useState, type FormEvent } from "react";
import { Link, useParams } from "react-router";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { client, type RepoResponse } from "@/client";
import {
  FolderPlus,
  GitFork,
  Plus,
  Search,
  Lock,
  Globe,
  Archive,
  Check,
  Download,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";

function formatSize(bytes: number) {
  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`;
}

function VisibilityTag({ visibility }: { visibility: string }) {
  if (visibility === "private") {
    return (
      <span className="inline-flex items-center gap-1 text-[11px] text-muted-foreground">
        <Lock className="size-3" />Private
      </span>
    );
  }
  return (
    <span className="inline-flex items-center gap-1 text-[11px] text-muted-foreground">
      <Globe className="size-3" />Public
    </span>
  );
}

function RepoRow({ repo, projectName }: { repo: RepoResponse; projectName: string }) {
  return (
    <Link
      className="group flex items-center gap-3 border-b border-border px-4 py-2.5 last:border-b-0 transition-colors hover:bg-muted/40"
      to={`/${projectName}/repo/${repo.name}`}
    >
      <GitFork className="size-4 text-muted-foreground shrink-0" />
      <div className="min-w-0 flex-1">
        <div className="flex items-baseline gap-1.5 flex-wrap">
          <span className="font-heading text-[13px] font-semibold text-foreground">{repo.name}</span>
          {repo.is_archived && (
            <span className="inline-flex items-center gap-1 text-[11px] text-muted-foreground">
              <Archive className="size-3" />Archived
            </span>
          )}
          <VisibilityTag visibility={repo.visibility} />
        </div>
        {repo.description && (
          <p className="text-[11px] text-muted-foreground truncate mt-0.5">{repo.description}</p>
        )}
      </div>
      <div className="shrink-0 flex items-center gap-4 font-mono text-[11px] text-muted-foreground">
        <span>{formatSize(repo.size_bytes)}</span>
        <span>{formatDate(repo.updated_at)}</span>
      </div>
    </Link>
  );
}

function RepoListView({
  projectName,
  onCreate,
}: {
  projectName: string;
  onCreate: () => void;
}) {
  const [search, setSearch] = useState("");

  const { data: repos = [], isLoading } = useQuery({
    queryKey: ["repos", projectName, search],
    queryFn: async () => {
      const res = await client.gitListRepos(projectName, { search: search || undefined });
      return res.data;
    },
    retry: false,
  });

  return (
    <>
      <div className="flex items-center justify-between">
        <h1 className="font-heading text-lg font-bold text-foreground">Repositories</h1>
        <Button className="h-9 rounded-xl px-3 text-[13px]" onClick={onCreate}>
          <Plus className="size-3.5 mr-1" />
          New repo
        </Button>
      </div>

      <div className="mt-6 overflow-hidden rounded-xl border border-border bg-card shadow-sm">
        <div className="flex items-center gap-2 border-b border-border bg-muted/40 px-3 py-2">
          <span className="font-mono text-[11px] text-muted-foreground">{repos.length} repositories</span>
          <div className="ml-auto relative">
            <Search className="absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
            <Input
              autoComplete="off"
              className="h-8 w-52 rounded-lg border-border bg-background pl-7 text-[12px]"
              placeholder="Filter repos..."
              value={search}
              onChange={(e) => setSearch(e.target.value)}
            />
          </div>
        </div>

        {isLoading ? (
          <div className="px-4 py-2">
            {Array.from({ length: 3 }).map((_, i) => (
              <div className="h-6 animate-pulse rounded bg-muted/50 my-1.5" key={i} />
            ))}
          </div>
        ) : repos.length > 0 ? (
          <div>
            {repos.map((repo) => (
              <RepoRow key={repo.id} projectName={projectName} repo={repo} />
            ))}
          </div>
        ) : (
          <div className="py-12 text-center">
            <FolderPlus className="mx-auto size-5 text-muted-foreground/20" />
            <p className="mt-3 text-[13px] text-muted-foreground">No repositories yet</p>
          </div>
        )}
      </div>
    </>
  );
}

type RepoCreateMode = "create" | "clone";

function RepoCreateView({
  projectName,
  onCancel,
}: {
  projectName: string;
  onCancel: () => void;
}) {
  const qc = useQueryClient();
  const [mode, setMode] = useState<RepoCreateMode>("create");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState("");

  // Shared
  const [name, setName] = useState("");
  const [description, setDescription] = useState("");
  const [visibility, setVisibility] = useState("private");

  // Create-only
  const [defaultBranch, setDefaultBranch] = useState("main");
  const [initReadme, setInitReadme] = useState(true);
  const [enableLfs, setEnableLfs] = useState(false);

  // Clone-only
  const [sourceUrl, setSourceUrl] = useState("");

  const handleCreate = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setError("");
    setSubmitting(true);

    if (!name.trim()) {
      setError("Name is required.");
      setSubmitting(false);
      return;
    }

    try {
      await client.gitCreateRepo(projectName, {
        name: name.trim(),
        description: description || null,
        visibility,
        default_branch: defaultBranch || null,
        initialize_with_readme: initReadme,
        enable_lfs: enableLfs,
      });
      await qc.invalidateQueries({ queryKey: ["repos", projectName] });
      onCancel();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to create repository.");
    } finally {
      setSubmitting(false);
    }
  };

  const handleClone = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setError("");
    setSubmitting(true);

    if (!name.trim()) {
      setError("Name is required.");
      setSubmitting(false);
      return;
    }
    if (!sourceUrl.trim()) {
      setError("Source URL is required.");
      setSubmitting(false);
      return;
    }

    try {
      await client.gitCloneRepo(projectName, {
        name: name.trim(),
        source_url: sourceUrl.trim(),
        description: description || null,
        visibility,
      });
      await qc.invalidateQueries({ queryKey: ["repos", projectName] });
      onCancel();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to clone repository.");
    } finally {
      setSubmitting(false);
    }
  };

  const handleSubmit = mode === "create" ? handleCreate : handleClone;

  const modeTabs: { key: RepoCreateMode; label: string; icon: React.ReactNode }[] = [
    { key: "create", label: "New", icon: <Plus className="size-3.5" /> },
    { key: "clone", label: "Clone", icon: <Download className="size-3.5" /> },
  ];

  return (
    <div className="max-w-2xl">
      <h1 className="font-heading text-lg font-bold text-foreground">
        Create a new repository
      </h1>
      <p className="mt-1 text-[13px] text-muted-foreground">
        A repository contains all project files, including the revision history.
      </p>

      {/* Mode tabs */}
      <div className="mt-5 flex gap-1 rounded-xl bg-muted/50 p-1">
        {modeTabs.map((tab) => (
          <button
            className={cn(
              "flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-1.5 text-[13px] font-medium transition-colors",
              mode === tab.key
                ? "bg-background text-foreground shadow-sm"
                : "text-muted-foreground hover:text-foreground",
            )}
            key={tab.key}
            onClick={() => { setMode(tab.key); setError(""); }}
            type="button"
          >
            {tab.icon}
            {tab.label}
          </button>
        ))}
      </div>

      <form className="mt-5 space-y-5" onSubmit={(e) => { e.preventDefault(); void handleSubmit(e); }}>
        {/* Source URL — clone only */}
        {mode === "clone" && (
          <div>
            <label className="text-[13px] font-medium text-foreground">Clone URL</label>
            <Input
              className="mt-1.5 h-9 text-[13px] font-mono"
              name="source_url"
              onChange={(e) => setSourceUrl(e.target.value)}
              placeholder="https://github.com/user/repo.git"
              required
              autoFocus
              value={sourceUrl}
            />
            <p className="mt-1 text-[11px] text-muted-foreground">
              The remote Git URL to clone from. Supports HTTPS and SSH.
            </p>
          </div>
        )}

        {/* Name */}
        <div>
          <label className="text-[13px] font-medium text-foreground">Repository name</label>
          <Input
            className="mt-1.5 h-9 text-[13px]"
            name="name"
            onChange={(e) => setName(e.target.value)}
            placeholder="e.g. my-project"
            required
            autoFocus={mode !== "clone"}
            value={name}
          />
          <p className="mt-1 text-[11px] text-muted-foreground">
            Great repository names are short and memorable.
          </p>
        </div>

        {/* Description */}
        <div>
          <label className="text-[13px] font-medium text-foreground">
            Description <span className="text-muted-foreground">(optional)</span>
          </label>
          <Textarea
            className="mt-1.5 min-h-[72px] text-[13px]"
            name="description"
            onChange={(e) => setDescription(e.target.value)}
            placeholder="A brief description of the repository"
            value={description}
          />
        </div>

        {/* Visibility */}
        <div>
          <label className="text-[13px] font-medium text-foreground">Visibility</label>
          <div className="mt-1.5 flex gap-2">
            {[
              { value: "private", icon: <Lock className="size-3.5" />, label: "Private", desc: "Only members can see this repository" },
              { value: "public", icon: <Globe className="size-3.5" />, label: "Public", desc: "Anyone can see this repository" },
            ].map((opt) => (
              <button
                className={cn(
                  "flex items-start gap-2 rounded-xl border p-3 text-left transition-colors",
                  visibility === opt.value
                    ? "border-primary bg-primary/5"
                    : "border-border hover:border-muted-foreground/30",
                )}
                key={opt.value}
                onClick={() => setVisibility(opt.value)}
                type="button"
              >
                <span className={cn("mt-0.5", visibility === opt.value ? "text-primary" : "text-muted-foreground")}>
                  {opt.icon}
                </span>
                <div>
                  <span className={cn("text-[13px] font-medium", visibility === opt.value ? "text-foreground" : "text-muted-foreground")}>
                    {opt.label}
                  </span>
                  <p className="text-[11px] text-muted-foreground">{opt.desc}</p>
                </div>
                {visibility === opt.value && (
                  <Check className="size-3.5 text-primary shrink-0 mt-0.5 ml-auto" />
                )}
              </button>
            ))}
          </div>
        </div>

        {/* Create-only fields */}
        {mode === "create" && (
          <>
            {/* Default branch */}
            <div>
              <label className="text-[13px] font-medium text-foreground">Default branch</label>
              <Input
                className="mt-1.5 h-9 w-48 text-[13px]"
                name="default_branch"
                onChange={(e) => setDefaultBranch(e.target.value)}
                value={defaultBranch}
              />
            </div>

            {/* Initialize */}
            <div>
              <label className="text-[13px] font-medium text-foreground">Initialize this repository</label>
              <div className="mt-2 space-y-2">
                <label className="flex items-center gap-2 cursor-pointer">
                  <input
                    checked={initReadme}
                    className="size-3.5 rounded border-border accent-primary"
                    onChange={(e) => setInitReadme(e.target.checked)}
                    type="checkbox"
                  />
                  <span className="text-[13px] text-foreground">Add a README file</span>
                </label>
                <label className="flex items-center gap-2 cursor-pointer">
                  <input
                    checked={enableLfs}
                    className="size-3.5 rounded border-border accent-primary"
                    onChange={(e) => setEnableLfs(e.target.checked)}
                    type="checkbox"
                  />
                  <span className="text-[13px] text-foreground">Enable Git LFS</span>
                </label>
              </div>
            </div>
          </>
        )}

        {error && (
          <p aria-live="polite" className="rounded-xl bg-destructive/10 px-3 py-2 text-[12px] text-destructive">{error}</p>
        )}

        {/* Actions */}
        <div className="flex items-center gap-3 pt-2">
          <Button className="h-9 px-4 text-[13px]" disabled={submitting} type="submit">
            {submitting
              ? mode === "create"
                ? "Creating..."
                : "Cloning..."
              : mode === "create"
                ? "Create repository"
                : "Clone repository"}
          </Button>
          <Button className="h-9 px-4 text-[13px]" onClick={onCancel} variant="outline">
            Cancel
          </Button>
        </div>
      </form>
    </div>
  );
}

export default function WorkspaceRepositoriesPage() {
  const { projectName = "" } = useParams();
  const [mode, setMode] = useState<"list" | "create">("list");

  return (
    <div className="px-8 py-10">
      {mode === "list" ? (
        <RepoListView projectName={projectName} onCreate={() => setMode("create")} />
      ) : (
        <RepoCreateView projectName={projectName} onCancel={() => setMode("list")} />
      )}
    </div>
  );
}