import { gitBranchList, gitUpdateRepo, projectExchangeName, projectExchangeVisibility, projectExchangeTitle } from "@/client";
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 { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  Edit2,
  GitBranch,
  GitCommit,
  Globe,
  Loader2,
  Lock,
} from "lucide-react";
import { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "sonner";
import { useRepo } from "@/contexts";
import {getApiErrorMessage} from '@/lib/api-error';

export function RepoSettingsGeneral() {
  const repo = useRepo();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const { namespace, repoName } = useParams<{ namespace: string; repoName: string }>();
  const ns = namespace!;
  const rn = repoName!;

  // Project name
  const [editingName, setEditingName] = useState(false);
  const [newName, setNewName] = useState(repo?.repo_name ?? "");

  // Visibility
  const visibilityMutation = useMutation({
    mutationFn: async (isPrivate: boolean) => {
      await projectExchangeVisibility({
        path: { project_name: ns },
        body: { is_public: !isPrivate },
      });
    },
    onSuccess: () => {
      toast.success("Visibility updated");
      queryClient.invalidateQueries({ queryKey: ["projectRepos", ns] });
    },
    onError: (err: unknown) => {
      toast.error(getApiErrorMessage(err, "Failed to update visibility"));
    },
  });

  // Default branch
  const [editingBranch, setEditingBranch] = useState(false);
  const [selectedBranch, setSelectedBranch] = useState(repo?.default_branch ?? "");

  const { data: branchesData } = useQuery({
    queryKey: ["repo-branches", ns, rn],
    queryFn: async () => {
      const resp = await gitBranchList({ path: { namespace: ns, repo: rn } });
      return resp.data?.data ?? [];
    },
    enabled: !!ns && !!rn && editingBranch,
    staleTime: 30 * 1000,
  });

  // Description
  const [descText, setDescText] = useState(repo?.description ?? "");
  const [descSaved, setDescSaved] = useState(true);

  useEffect(() => {
    if (repo) {
      setDescText(repo.description ?? "");
      setDescSaved(true);
    }
  }, [repo?.description]);

  useEffect(() => {
    if (repo) setSelectedBranch(repo.default_branch ?? "");
  }, [repo?.default_branch]);

  const nameMutation = useMutation({
    mutationFn: async () => {
      if (!newName.trim() || newName === repo?.repo_name) return;
      await projectExchangeName({
        path: { project_name: ns },
        body: { name: newName.trim() },
      });
    },
    onSuccess: () => {
      toast.success("Repository renamed");
      queryClient.invalidateQueries({ queryKey: ["projectRepos", ns] });
      navigate(`/repository/${newName}/${rn}/settings`);
    },
    onError: (err: unknown) => {
      toast.error(getApiErrorMessage(err, "Failed to rename repository"));
    },
  });

  const branchMutation = useMutation({
    mutationFn: async () => {
      if (!selectedBranch || selectedBranch === repo?.default_branch) return;
      await gitUpdateRepo({
        path: { namespace: ns, repo: rn },
        body: { default_branch: selectedBranch },
      });
    },
    onSuccess: () => {
      toast.success("Default branch updated");
      queryClient.invalidateQueries({ queryKey: ["projectRepos", ns] });
      setEditingBranch(false);
    },
    onError: (err: unknown) => {
      toast.error(getApiErrorMessage(err, "Failed to update default branch"));
    },
  });

  const descMutation = useMutation({
    mutationFn: async () => {
      await projectExchangeTitle({
        path: { project_name: ns },
        body: { description: descText.trim() || null },
      });
    },
    onSuccess: () => {
      toast.success("Description updated");
      queryClient.invalidateQueries({ queryKey: ["projectRepos", ns] });
      setDescSaved(true);
    },
    onError: (err: unknown) => {
      toast.error(getApiErrorMessage(err, "Failed to update description"));
    },
  });

  const branches: Array<{ name: string }> = branchesData ?? [];

  if (!repo) return null;

  return (
    <div className="space-y-4">
      {/* Repository Info */}
      <div className="border rounded-lg bg-card">
        <div className="p-4 border-b">
          <h2 className="text-sm font-semibold">Repository Info</h2>
        </div>
        <div className="p-4 space-y-4">
          <div className="grid grid-cols-2 gap-6">
            {/* Name */}
            <div>
              <Label className="text-muted-foreground text-xs uppercase tracking-wide">Repository Name</Label>
              {editingName ? (
                <div className="flex items-center gap-2 mt-0.5">
                  <Input
                    value={newName}
                    onChange={(e) => setNewName(e.target.value)}
                    className="h-8 font-mono text-sm"
                    autoFocus
                  />
                  <Button size="sm" onClick={() => nameMutation.mutate()} disabled={nameMutation.isPending || !newName.trim()}>
                    {nameMutation.isPending ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : "Save"}
                  </Button>
                  <Button size="sm" variant="outline" onClick={() => { setEditingName(false); setNewName(repo.repo_name); }}>
                    Cancel
                  </Button>
                </div>
              ) : (
                <div className="flex items-center gap-2 mt-0.5">
                  <p className="font-medium font-mono">{repo.repo_name}</p>
                  <button
                    onClick={() => { setEditingName(true); setNewName(repo.repo_name); }}
                    className="p-1 hover:bg-muted rounded transition-colors"
                  >
                    <Edit2 className="h-3.5 w-3.5 text-muted-foreground" />
                  </button>
                </div>
              )}
            </div>

            {/* Namespace */}
            <div>
              <Label className="text-muted-foreground text-xs uppercase tracking-wide">Namespace</Label>
              <p className="font-medium mt-0.5">{repo.namespace}</p>
            </div>

            {/* Default Branch */}
            <div>
              <Label className="text-muted-foreground text-xs uppercase tracking-wide">Default Branch</Label>
              {editingBranch ? (
                <div className="flex items-center gap-2 mt-0.5">
                  <select
                    value={selectedBranch}
                    onChange={(e) => setSelectedBranch(e.target.value)}
                    className="h-8 px-2 text-sm border rounded bg-background"
                  >
                    {branches.map((b) => (
                      <option key={b.name} value={b.name}>{b.name}</option>
                    ))}
                  </select>
                  <Button
                    size="sm"
                    onClick={() => branchMutation.mutate()}
                    disabled={branchMutation.isPending || selectedBranch === repo.default_branch}
                  >
                    {branchMutation.isPending ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : "Save"}
                  </Button>
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={() => { setEditingBranch(false); setSelectedBranch(repo.default_branch); }}
                  >
                    Cancel
                  </Button>
                </div>
              ) : (
                <div className="flex items-center gap-2 mt-0.5">
                  <p className="font-medium flex items-center gap-1.5">
                    <GitBranch className="h-4 w-4 text-muted-foreground" />
                    {repo.default_branch}
                  </p>
                  <button
                    onClick={() => { setEditingBranch(true); setSelectedBranch(repo.default_branch); }}
                    className="p-1 hover:bg-muted rounded transition-colors"
                  >
                    <Edit2 className="h-3.5 w-3.5 text-muted-foreground" />
                  </button>
                </div>
              )}
            </div>

            {/* Visibility */}
            <div>
              <Label className="text-muted-foreground text-xs uppercase tracking-wide">Visibility</Label>
              <div className="flex items-center gap-3 mt-0.5">
                <button
                  onClick={() => visibilityMutation.mutate(repo.is_private)}
                  disabled={visibilityMutation.isPending}
                  className="flex items-center gap-1.5 px-3 py-1.5 rounded-md border text-sm font-medium border-border bg-muted/50 text-foreground hover:bg-muted transition-colors"
                >
                  {repo.is_private ? <Lock className="h-4 w-4" /> : <Globe className="h-4 w-4" />}
                  {repo.is_private ? "Private" : "Public"}
                </button>
                {visibilityMutation.isPending && <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />}
              </div>
            </div>

            {/* Stats */}
            <div>
              <Label className="text-muted-foreground text-xs uppercase tracking-wide">Commits</Label>
              <p className="font-medium mt-0.5 flex items-center gap-1.5">
                <GitCommit className="h-4 w-4 text-muted-foreground" />
                {(repo.commit_count ?? 0).toLocaleString()}
              </p>
            </div>
            <div>
              <Label className="text-muted-foreground text-xs uppercase tracking-wide">Branches</Label>
              <p className="font-medium mt-0.5">{(repo as any).branch_count ?? 0}</p>
            </div>
          </div>
        </div>
      </div>

      {/* Description */}
      <div className="border rounded-lg bg-card">
        <div className="p-4 border-b flex items-center justify-between">
          <div>
            <h2 className="text-sm font-semibold">Description</h2>
            <p className="text-xs text-muted-foreground mt-0.5">Project description shown on the overview page</p>
          </div>
          {!descSaved && (
            <Button size="sm" onClick={() => descMutation.mutate()} disabled={descMutation.isPending}>
              {descMutation.isPending && <Loader2 className="h-3.5 w-3.5 mr-1 animate-spin" />}
              Save
            </Button>
          )}
        </div>
        <div className="p-4">
          <Textarea
            value={descText}
            onChange={(e) => { setDescText(e.target.value); setDescSaved(false); }}
            placeholder="Add a description..."
            rows={3}
            className="resize-none"
          />
        </div>
      </div>
    </div>
  );
}
