import { useState, type FormEvent } from "react";
import { useParams, useNavigate } from "react-router";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { client } from "@/client";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
import { Lock, Globe, Archive, ArchiveRestore, Shield, Hash, Trash2, ArrowRight, GitFork } from "lucide-react";

export default function RepoSettingsTab() {
  const { projectName = "", repoName = "" } = useParams();
  const qc = useQueryClient();
  const navigate = useNavigate();
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState("");

  const { data: repo } = 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 [visibility, setVisibility] = useState(repo?.visibility ?? "private");
  const [isArchived, setIsArchived] = useState(repo?.is_archived ?? false);
  const [defaultBranch, setDefaultBranch] = useState(repo?.default_branch ?? "");

  // Topics state
  const [topicsInput, setTopicsInput] = useState("");
  const [transferTarget, setTransferTarget] = useState("");

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

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

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

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

  const hasBranches = branches && branches.length > 0;

  const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setError("");
    setSubmitting(true);
    const form = new FormData(event.currentTarget);
    const name = (form.get("name") as string) || null;
    const description = (form.get("description") as string) || null;
    try {
      await client.gitUpdateRepo(projectName, repoName, { name, description, visibility, default_branch: defaultBranch, is_archived: isArchived });
      await qc.invalidateQueries({ queryKey: ["repo", projectName, repoName] });
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to update repository.");
    } finally { setSubmitting(false); }
  };

  const updateTopics = useMutation({
    mutationFn: async () => {
      const list = topicsInput.split(",").map((t) => t.trim()).filter(Boolean);
      await client.gitUpdateTopics(projectName, repoName, list);
    },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["repo", projectName, repoName, "topics"] }),
  });

  const deleteRepo = useMutation({
    mutationFn: async () => { await client.gitDeleteRepo(projectName, repoName); },
    onSuccess: () => { navigate(`/${projectName}/repos`); },
  });

  const transferRepo = useMutation({
    mutationFn: async () => { await client.gitTransferRepo(projectName, repoName, { target_workspace: transferTarget }); },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["repo", projectName, repoName] }),
  });

  const createProtect = useMutation({
    mutationFn: async (pattern: string) => { await client.gitCreateProtect(projectName, repoName, { pattern, require_pull_request: true, required_approvals: 1 }); },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["repo", projectName, repoName, "protects"] }),
  });

  const deleteProtect = useMutation({
    mutationFn: async (id: string) => { await client.gitDeleteProtect(projectName, repoName, id); },
    onSuccess: () => qc.invalidateQueries({ queryKey: ["repo", projectName, repoName, "protects"] }),
  });

  const [newProtectPattern, setNewProtectPattern] = useState("");

  if (!repo) {
    return (
      <div className="space-y-3">
        {Array.from({ length: 4 }).map((_, i) => <div className="h-8 animate-pulse rounded bg-muted/50" key={i} />)}
      </div>
    );
  }

  return (
    <div className="space-y-8">
      {/* Repo settings form */}
      <form className="space-y-5" onSubmit={(e) => void handleSubmit(e)}>
        <h2 className="font-heading text-[15px] font-bold text-foreground">General</h2>
        <div>
          <label className="text-[13px] font-medium text-foreground">Repository name</label>
          <Input className="mt-1 h-9 text-[13px]" name="name" defaultValue={repo.name} />
          <p className="mt-0.5 text-[11px] text-muted-foreground">Changing the name will also change the repository URL.</p>
        </div>
        <div>
          <label className="text-[13px] font-medium text-foreground">Description <span className="text-muted-foreground">(optional)</span></label>
          <Textarea className="mt-1 min-h-[72px] text-[13px]" name="description" defaultValue={repo.description ?? ""} />
        </div>
        <div>
          <label className="text-[13px] font-medium text-foreground">Default branch</label>
          {hasBranches ? (
            <Select value={defaultBranch} onValueChange={(v) => setDefaultBranch(v ?? "")}>
              <SelectTrigger className="mt-1 h-9 w-48 text-[13px]"><SelectValue /></SelectTrigger>
              <SelectContent>{branches!.map((b) => <SelectItem key={b.name} value={b.name}>{b.name}</SelectItem>)}</SelectContent>
            </Select>
          ) : (
            <Input className="mt-1 h-9 w-48 text-[13px]" name="default_branch" defaultValue={repo.default_branch} onChange={(e) => setDefaultBranch(e.target.value)} />
          )}
        </div>
        <div>
          <label className="text-[13px] font-medium text-foreground">Visibility</label>
          <div className="mt-1 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-md 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>
              </button>
            ))}
          </div>
        </div>
        <div>
          <label className="flex items-center gap-2 cursor-pointer">
            <input checked={isArchived} className="size-3.5 rounded border-border accent-primary" onChange={(e) => setIsArchived(e.target.checked)} type="checkbox" />
            <span className="text-[13px] text-foreground">Archive this repository</span>
            <span className="text-[11px] text-muted-foreground">{isArchived ? <ArchiveRestore className="size-3 inline" /> : <Archive className="size-3 inline" />}{isArchived ? " Unarchive to allow changes" : " Read-only, no changes allowed"}</span>
          </label>
        </div>
        {error && <p className="text-[12px] text-destructive">{error}</p>}
        <div className="flex items-center gap-3 pt-2">
          <Button className="h-9 px-4 text-[13px]" disabled={submitting} type="submit">{submitting ? "Saving..." : "Save changes"}</Button>
        </div>
      </form>

      {/* Topics */}
      <div className="space-y-3">
        <h2 className="font-heading text-[15px] font-bold text-foreground flex items-center gap-2"><Hash className="size-4" /> Topics</h2>
        <div className="flex flex-wrap gap-1.5 mb-2">
          {topics.map((t) => (
            <span className="inline-flex items-center gap-1 rounded-full bg-primary/10 px-2.5 py-0.5 font-mono text-[11px] text-primary" key={t}>
              #{t}
              <button className="text-primary/60 hover:text-primary" onClick={() => {
                const next = topics.filter((x) => x !== t);
                client.gitUpdateTopics(projectName, repoName, next);
                qc.invalidateQueries({ queryKey: ["repo", projectName, repoName, "topics"] });
              }}>&times;</button>
            </span>
          ))}
        </div>
        <div className="flex items-center gap-2">
          <Input className="h-9 text-[13px] flex-1" placeholder="e.g. rust, cli, database" value={topicsInput} onChange={(e) => setTopicsInput(e.target.value)} />
          <Button className="h-9 px-3 text-[13px]" disabled={!topicsInput.trim() || updateTopics.isPending} onClick={() => updateTopics.mutate()}>Update</Button>
        </div>
      </div>

      {/* Fork info */}
      {forks.length > 0 && (
        <div className="space-y-3">
          <h2 className="font-heading text-[15px] font-bold text-foreground flex items-center gap-2"><GitFork className="size-4" /> Forks ({forks.length})</h2>
          <div className="rounded-md border border-border overflow-hidden">
            {forks.map((f) => (
              <div className="flex items-center gap-3 border-b border-border px-4 py-2.5 last:border-b-0" key={f.id}>
                <GitFork className="size-4 text-muted-foreground shrink-0" />
                <span className="font-heading text-[13px] font-semibold text-foreground">{f.name}</span>
                <span className="font-mono text-[10px] text-muted-foreground">{f.visibility}</span>
                {f.forked_by && <span className="font-mono text-[11px] text-muted-foreground ml-auto">forked by {f.forked_by}</span>}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Branch protections */}
      <div className="space-y-3">
        <h2 className="font-heading text-[15px] font-bold text-foreground flex items-center gap-2"><Shield className="size-4" /> Branch protection rules</h2>
        {protects.length > 0 && (
          <div className="rounded-md border border-border overflow-hidden mb-3">
            {protects.map((p) => (
              <div className="flex items-center gap-3 border-b border-border px-4 py-2.5 last:border-b-0" key={p.id}>
                <Shield className="size-4 text-primary shrink-0" />
                <span className="font-heading text-[13px] font-semibold text-foreground">{p.pattern}</span>
                {p.require_pull_request && <span className="font-mono text-[10px] text-muted-foreground">requires PR</span>}
                <span className="font-mono text-[10px] text-muted-foreground">{p.required_approvals > 0 ? `${p.required_approvals} approval(s)` : ""}</span>
                <Button aria-label="Delete branch protection rule" className="ml-auto size-8 text-destructive hover:text-destructive" onClick={() => deleteProtect.mutate(p.id)} size="icon" variant="ghost">
                  <Trash2 className="size-3.5" />
                </Button>
              </div>
            ))}
          </div>
        )}
        <div className="flex items-center gap-2">
          <Input className="h-9 text-[13px] flex-1" placeholder="Branch pattern (e.g. main, release/*)" value={newProtectPattern} onChange={(e) => setNewProtectPattern(e.target.value)} />
          <Button className="h-9 px-3 text-[13px]" disabled={!newProtectPattern.trim()} onClick={() => { createProtect.mutate(newProtectPattern.trim()); setNewProtectPattern(""); }}>Add rule</Button>
        </div>
      </div>

      {/* Danger Zone */}
      <div className="space-y-3 rounded-md border border-red-900/30 p-4">
        <h2 className="font-heading text-[15px] font-bold text-destructive flex items-center gap-2"><Trash2 className="size-4" /> Danger Zone</h2>
        <div className="flex items-center justify-between">
          <div>
            <p className="text-[13px] font-medium text-foreground">Transfer ownership</p>
            <p className="text-[11px] text-muted-foreground">Move this repository to another workspace.</p>
          </div>
          <div className="flex items-center gap-2">
            <Input className="h-8 w-44 text-[12px]" placeholder="Target workspace" value={transferTarget} onChange={(e) => setTransferTarget(e.target.value)} />
            <Button className="h-8 px-3 text-[12px]" disabled={!transferTarget.trim() || transferRepo.isPending} onClick={() => { if (confirm(`Transfer to ${transferTarget}?`)) transferRepo.mutate(); }} variant="outline">
              <ArrowRight className="size-3 mr-1" /> Transfer
            </Button>
          </div>
        </div>
        <div className="flex items-center justify-between pt-2 border-t border-red-900/30">
          <div>
            <p className="text-[13px] font-medium text-foreground">Delete this repository</p>
            <p className="text-[11px] text-muted-foreground">Once deleted, it cannot be recovered.</p>
          </div>
          <Button className="h-8 px-3 text-[12px]" disabled={deleteRepo.isPending} onClick={() => { if (confirm(`Permanently delete "${repoName}"? This cannot be undone.`)) deleteRepo.mutate(); }} variant="outline">
            <Trash2 className="size-3 mr-1" /> Delete
          </Button>
        </div>
      </div>
    </div>
  );
}