import { type UseMutationResult, useMutation, useQueryClient } from '@tanstack/react-query';
import { GitBranch, Plus, Search, Star, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { useParams } from 'react-router-dom';
import { ReposService } from '@/client/services/ReposService';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Spinner } from '@/components/ui/spinner';
import { useRepoBranches } from '@/hooks/repo/useRepoBranches';
import { cn } from '@/lib/utils';

export function RepoBranchesPage() {
  const { workspaceName = '', repoName = '' } = useParams();
  const qc = useQueryClient();
  const { data: branches, isLoading } = useRepoBranches(workspaceName, repoName);

  const [search, setSearch] = useState('');
  const [showCreate, setShowCreate] = useState(false);
  const [newName, setNewName] = useState('');
  const [newSource, setNewSource] = useState('');

  const createBranch = useMutation({
    mutationFn: () =>
      ReposService.repoCreateBranch({
        workspaceName,
        repoName,
        requestBody: { branch_name: newName, start_point: newSource || 'HEAD' },
      }),
    onSuccess: () => {
      setNewName('');
      setNewSource('');
      setShowCreate(false);
      qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName, 'branches'] });
    },
  });

  const deleteBranch = useMutation({
    mutationFn: (branchName: string) =>
      ReposService.repoDeleteBranch({ workspaceName, repoName, branchName }),
    onSuccess: () =>
      qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName, 'branches'] }),
  });

  const setDefault = useMutation({
    mutationFn: (branchName: string) =>
      ReposService.repoSetDefaultBranch({ workspaceName, repoName, branchName }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName, 'branches'] });
      qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName] });
    },
  });

  const list = branches ?? [];
  const filtered = search
    ? list.filter((b) => b.name.toLowerCase().includes(search.toLowerCase()))
    : list;

  const defaultBranches = filtered.filter((b) => b.is_default);
  const otherBranches = filtered.filter((b) => !b.is_default);

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2">
        <div className="relative flex-1 max-w-[300px]">
          <Search className="absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
          <Input
            className="h-8 pl-8 text-[13px]"
            placeholder="Find a branch..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
        <Button size="sm" className="ml-auto" onClick={() => setShowCreate(!showCreate)}>
          <Plus className="size-3.5" />
          New branch
        </Button>
      </div>

      {showCreate && (
        <div className="flex items-center gap-2 rounded-lg border border-border p-3">
          <Input
            className="h-8 flex-1 text-[13px]"
            placeholder="Branch name"
            value={newName}
            onChange={(e) => setNewName(e.target.value)}
          />
          <Input
            className="h-8 w-40 text-[13px]"
            placeholder="Source (branch/commit)"
            value={newSource}
            onChange={(e) => setNewSource(e.target.value)}
          />
          <Button
            size="sm"
            disabled={!newName.trim() || createBranch.isPending}
            onClick={() => createBranch.mutate()}
          >
            Create
          </Button>
          <Button size="sm" variant="outline" onClick={() => setShowCreate(false)}>
            Cancel
          </Button>
        </div>
      )}

      <div className="overflow-hidden rounded-lg border border-border">
        {isLoading ? (
          <div className="flex items-center gap-2 p-6 text-[13px] text-muted-foreground">
            <Spinner />
          </div>
        ) : filtered.length > 0 ? (
          <div>
            {defaultBranches.map((b) => (
              <BranchRow
                key={b.name}
                branch={b}
                isDefault
                onDelete={deleteBranch}
                onSetDefault={setDefault}
              />
            ))}
            {otherBranches.length > 0 && defaultBranches.length > 0 && (
              <div className="border-b border-border bg-muted/30 px-4 py-1.5">
                <span className="text-[10px] uppercase tracking-wider text-muted-foreground">
                  Other branches
                </span>
              </div>
            )}
            {otherBranches.map((b) => (
              <BranchRow key={b.name} branch={b} onDelete={deleteBranch} onSetDefault={setDefault} />
            ))}
          </div>
        ) : (
          <div className="flex flex-col items-center justify-center py-16 text-center">
            <GitBranch className="size-6 text-muted-foreground/30" />
            <p className="mt-3 text-[13px] text-muted-foreground">
              {search ? `No branches matching "${search}"` : 'No branches yet'}
            </p>
          </div>
        )}
      </div>
    </div>
  );
}

interface BranchRowProps {
  branch: {
    name: string;
    commit?: { abbreviated_oid?: string } | null;
    is_default?: boolean;
    is_merged?: boolean;
  };
  isDefault?: boolean;
  onDelete: UseMutationResult<unknown, unknown, string>;
  onSetDefault: UseMutationResult<unknown, unknown, string>;
}

function BranchRow({ branch, isDefault, onDelete, onSetDefault }: BranchRowProps) {
  const commitSha = branch.commit?.abbreviated_oid ?? '';
  const isDef = isDefault || branch.is_default;

  return (
    <div className="flex items-center gap-3 border-b border-border px-4 py-2.5 last:border-b-0 transition-colors hover:bg-muted/40">
      <GitBranch
        className={cn('size-4 shrink-0', isDef ? 'text-primary' : 'text-muted-foreground')}
      />
      <span className="text-[13px] font-semibold text-foreground">{branch.name}</span>
      {isDef && (
        <span className="inline-flex items-center gap-0.5 rounded border border-primary/30 bg-primary/5 px-1.5 py-0.5 text-[10px] text-primary">
          <Star className="size-2.5" />
          Default
        </span>
      )}
      {branch.is_merged && (
        <span className="rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground">
          Merged
        </span>
      )}
      {commitSha && (
        <code className="ml-auto text-[10px] text-muted-foreground/60">{commitSha.slice(0, 7)}</code>
      )}
      {!isDef && (
        <div className="flex items-center gap-0.5">
          <Button
            size="icon-sm"
            variant="ghost"
            className="text-muted-foreground hover:text-foreground"
            onClick={() => onSetDefault.mutate(branch.name)}
            title="Set as default branch"
          >
            <Star className="size-3" />
          </Button>
          <Button
            size="icon-sm"
            variant="ghost"
            className="text-muted-foreground hover:text-destructive"
            onClick={() => {
              if (confirm(`Delete branch "${branch.name}"?`)) onDelete.mutate(branch.name);
            }}
          >
            <Trash2 className="size-3.5" />
          </Button>
        </div>
      )}
    </div>
  );
}
