import { useState, useEffect } from 'react'; import { createLogger } from '@automaker/utils/logger'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { getHttpApiClient } from '@/lib/http-api-client'; import { toast } from 'sonner'; import { GitMerge, RefreshCw, AlertTriangle } from 'lucide-react'; import { Spinner } from '@/components/ui/spinner'; interface WorktreeInfo { path: string; branch: string; isMain: boolean; hasChanges?: boolean; changedFilesCount?: number; } interface RemoteBranch { name: string; fullRef: string; } interface RemoteInfo { name: string; url: string; branches: RemoteBranch[]; } const logger = createLogger('PullResolveConflictsDialog'); interface PullResolveConflictsDialogProps { open: boolean; onOpenChange: (open: boolean) => void; worktree: WorktreeInfo | null; onConfirm: (worktree: WorktreeInfo, remoteBranch: string) => void; } export function PullResolveConflictsDialog({ open, onOpenChange, worktree, onConfirm, }: PullResolveConflictsDialogProps) { const [remotes, setRemotes] = useState([]); const [selectedRemote, setSelectedRemote] = useState(''); const [selectedBranch, setSelectedBranch] = useState(''); const [isLoading, setIsLoading] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false); const [error, setError] = useState(null); // Fetch remotes when dialog opens useEffect(() => { if (open && worktree) { fetchRemotes(); } }, [open, worktree]); // Reset state when dialog closes useEffect(() => { if (!open) { setSelectedRemote(''); setSelectedBranch(''); setError(null); } }, [open]); // Auto-select default remote and branch when remotes are loaded useEffect(() => { if (remotes.length > 0 && !selectedRemote) { // Default to 'origin' if available, otherwise first remote const defaultRemote = remotes.find((r) => r.name === 'origin') || remotes[0]; setSelectedRemote(defaultRemote.name); // Try to select a matching branch name or default to main/master if (defaultRemote.branches.length > 0 && worktree) { const matchingBranch = defaultRemote.branches.find((b) => b.name === worktree.branch); const mainBranch = defaultRemote.branches.find( (b) => b.name === 'main' || b.name === 'master' ); const defaultBranch = matchingBranch || mainBranch || defaultRemote.branches[0]; setSelectedBranch(defaultBranch.fullRef); } } }, [remotes, selectedRemote, worktree]); // Update selected branch when remote changes useEffect(() => { if (selectedRemote && remotes.length > 0 && worktree) { const remote = remotes.find((r) => r.name === selectedRemote); if (remote && remote.branches.length > 0) { // Try to select a matching branch name or default to main/master const matchingBranch = remote.branches.find((b) => b.name === worktree.branch); const mainBranch = remote.branches.find((b) => b.name === 'main' || b.name === 'master'); const defaultBranch = matchingBranch || mainBranch || remote.branches[0]; setSelectedBranch(defaultBranch.fullRef); } else { setSelectedBranch(''); } } }, [selectedRemote, remotes, worktree]); const fetchRemotes = async () => { if (!worktree) return; setIsLoading(true); setError(null); try { const api = getHttpApiClient(); const result = await api.worktree.listRemotes(worktree.path); if (result.success && result.result) { setRemotes(result.result.remotes); if (result.result.remotes.length === 0) { setError('No remotes found in this repository'); } } else { setError(result.error || 'Failed to fetch remotes'); } } catch (err) { logger.error('Failed to fetch remotes:', err); setError('Failed to fetch remotes'); } finally { setIsLoading(false); } }; const handleRefresh = async () => { if (!worktree) return; setIsRefreshing(true); setError(null); try { const api = getHttpApiClient(); const result = await api.worktree.listRemotes(worktree.path); if (result.success && result.result) { setRemotes(result.result.remotes); toast.success('Remotes refreshed'); } else { toast.error(result.error || 'Failed to refresh remotes'); } } catch (err) { logger.error('Failed to refresh remotes:', err); toast.error('Failed to refresh remotes'); } finally { setIsRefreshing(false); } }; const handleConfirm = () => { if (!worktree || !selectedBranch) return; onConfirm(worktree, selectedBranch); onOpenChange(false); }; const selectedRemoteData = remotes.find((r) => r.name === selectedRemote); const branches = selectedRemoteData?.branches || []; return ( Pull & Resolve Conflicts Select a remote branch to pull from and resolve conflicts with{' '} {worktree?.branch || 'current branch'} {isLoading ? (
) : error ? (
{error}
) : (
{selectedRemote && branches.length === 0 && (

No branches found for this remote

)}
{selectedBranch && (

This will create a feature task to pull from{' '} {selectedBranch} into{' '} {worktree?.branch} and resolve any merge conflicts.

)}
)}
); }