import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Git Status Tool
 *
 * Shows repository status including branch, changes, and sync state.
 */
import { Box, Text } from 'ink';
import { useTerminalWidth } from '../../hooks/useTerminalWidth.js';
import { useTheme } from '../../hooks/useTheme.js';
import { jsonSchema, tool } from '../../types/core.js';
import { formatError } from '../../utils/error-formatter.js';
import { execGit, formatStatusChar, getAheadBehind, getCurrentBranch, getDiffStats, getStashCount, getUpstreamBranch, isMergeInProgress, isRebaseInProgress, parseGitStatus, } from './utils.js';
// ============================================================================
// Execution
// ============================================================================
async function getStatus() {
    // Get branch info
    const branch = await getCurrentBranch();
    const upstream = await getUpstreamBranch();
    const { ahead, behind } = await getAheadBehind();
    // Get status
    const statusOutput = await execGit(['status', '--porcelain']);
    const { staged, unstaged, untracked, conflicts } = parseGitStatus(statusOutput);
    // Get diff stats for staged files
    const stagedStats = await getDiffStats(true);
    for (const file of staged) {
        const stats = stagedStats.get(file.path);
        if (stats) {
            file.additions = stats.additions;
            file.deletions = stats.deletions;
        }
    }
    // Get diff stats for unstaged files
    const unstagedStats = await getDiffStats(false);
    for (const file of unstaged) {
        const stats = unstagedStats.get(file.path);
        if (stats) {
            file.additions = stats.additions;
            file.deletions = stats.deletions;
        }
    }
    // Calculate totals
    const totalAdditions = staged.reduce((sum, f) => sum + f.additions, 0) +
        unstaged.reduce((sum, f) => sum + f.additions, 0);
    const totalDeletions = staged.reduce((sum, f) => sum + f.deletions, 0) +
        unstaged.reduce((sum, f) => sum + f.deletions, 0);
    // Get additional state
    const stashCount = await getStashCount();
    const isRebase = await isRebaseInProgress();
    const isMerge = await isMergeInProgress();
    return {
        branch,
        upstream,
        ahead,
        behind,
        staged,
        unstaged,
        untracked,
        conflicts,
        stashCount,
        isRebase,
        isMerge,
        totalAdditions,
        totalDeletions,
    };
}
const executeGitStatus = async (_args) => {
    try {
        const status = await getStatus();
        const lines = [];
        // Branch info
        lines.push(`Branch: ${status.branch}`);
        if (status.upstream) {
            lines.push(`Upstream: ${status.upstream}`);
            if (status.ahead > 0 || status.behind > 0) {
                const parts = [];
                if (status.ahead > 0)
                    parts.push(`${status.ahead} ahead`);
                if (status.behind > 0)
                    parts.push(`${status.behind} behind`);
                lines.push(`Sync: ${parts.join(', ')}`);
            }
        }
        else {
            lines.push('Upstream: not set');
        }
        lines.push('');
        // Special states
        if (status.isRebase) {
            lines.push('STATE: Rebase in progress');
            lines.push('');
        }
        if (status.isMerge) {
            lines.push('STATE: Merge in progress');
            lines.push('');
        }
        // Conflicts
        if (status.conflicts.length > 0) {
            lines.push(`CONFLICTS (${status.conflicts.length}):`);
            for (const file of status.conflicts.slice(0, 10)) {
                lines.push(`  UU ${file}`);
            }
            if (status.conflicts.length > 10) {
                lines.push(`  ... and ${status.conflicts.length - 10} more`);
            }
            lines.push('');
        }
        // Staged changes
        if (status.staged.length > 0) {
            const stagedAdd = status.staged.reduce((s, f) => s + f.additions, 0);
            const stagedDel = status.staged.reduce((s, f) => s + f.deletions, 0);
            lines.push(`Staged (${status.staged.length} files, +${stagedAdd}, -${stagedDel}):`);
            for (const file of status.staged.slice(0, 10)) {
                const char = formatStatusChar(file.status);
                lines.push(`  ${char}  ${file.path}`);
            }
            if (status.staged.length > 10) {
                lines.push(`  ... and ${status.staged.length - 10} more`);
            }
            lines.push('');
        }
        // Unstaged changes
        if (status.unstaged.length > 0) {
            const unstagedAdd = status.unstaged.reduce((s, f) => s + f.additions, 0);
            const unstagedDel = status.unstaged.reduce((s, f) => s + f.deletions, 0);
            lines.push(`Modified (${status.unstaged.length} files, +${unstagedAdd}, -${unstagedDel}):`);
            for (const file of status.unstaged.slice(0, 10)) {
                const char = formatStatusChar(file.status);
                lines.push(`  ${char}  ${file.path}`);
            }
            if (status.unstaged.length > 10) {
                lines.push(`  ... and ${status.unstaged.length - 10} more`);
            }
            lines.push('');
        }
        // Untracked files
        if (status.untracked.length > 0) {
            lines.push(`Untracked (${status.untracked.length} files):`);
            for (const file of status.untracked.slice(0, 10)) {
                lines.push(`  ?  ${file}`);
            }
            if (status.untracked.length > 10) {
                lines.push(`  ... and ${status.untracked.length - 10} more`);
            }
            lines.push('');
        }
        // Stash
        if (status.stashCount > 0) {
            lines.push(`Stash: ${status.stashCount} stashed change(s)`);
            lines.push('');
        }
        // Clean state
        if (status.staged.length === 0 &&
            status.unstaged.length === 0 &&
            status.untracked.length === 0 &&
            status.conflicts.length === 0) {
            lines.push('Working tree clean');
        }
        return lines.join('\n');
    }
    catch (error) {
        return `Error: ${formatError(error)}`;
    }
};
// ============================================================================
// Tool Definition
// ============================================================================
const gitStatusCoreTool = tool({
    description: 'Show git repository status including branch, staged/unstaged changes, and sync state with remote.',
    inputSchema: jsonSchema({
        type: 'object',
        properties: {},
        required: [],
    }),
    execute: async (args, _options) => {
        return await executeGitStatus(args);
    },
});
// ============================================================================
// Formatter
// ============================================================================
function GitStatusFormatter({ result }) {
    const boxWidth = useTerminalWidth();
    const { colors } = useTheme();
    // Parse result for display
    let branch = '';
    let ahead = 0;
    let behind = 0;
    let stagedCount = 0;
    let modifiedCount = 0;
    let untrackedCount = 0;
    let hasConflicts = false;
    if (result) {
        const branchMatch = result.match(/Branch: (.+)/);
        if (branchMatch)
            branch = branchMatch[1];
        const syncMatch = result.match(/Sync: (.+)/);
        if (syncMatch) {
            const aheadMatch = syncMatch[1].match(/(\d+) ahead/);
            const behindMatch = syncMatch[1].match(/(\d+) behind/);
            if (aheadMatch)
                ahead = parseInt(aheadMatch[1], 10);
            if (behindMatch)
                behind = parseInt(behindMatch[1], 10);
        }
        const stagedMatch = result.match(/Staged \((\d+) files/);
        if (stagedMatch)
            stagedCount = parseInt(stagedMatch[1], 10);
        const modifiedMatch = result.match(/Modified \((\d+) files/);
        if (modifiedMatch)
            modifiedCount = parseInt(modifiedMatch[1], 10);
        const untrackedMatch = result.match(/Untracked \((\d+) files/);
        if (untrackedMatch)
            untrackedCount = parseInt(untrackedMatch[1], 10);
        hasConflicts = result.includes('CONFLICTS');
    }
    return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, width: boxWidth, children: [_jsx(Text, { color: colors.tool, children: "\u2692 git_status" }), branch && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Branch: " }), _jsx(Text, { color: colors.primary, children: branch })] })), (ahead > 0 || behind > 0) && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Sync: " }), ahead > 0 && _jsxs(Text, { color: colors.success, children: [ahead, " ahead"] }), ahead > 0 && behind > 0 && _jsx(Text, { color: colors.secondary, children: ", " }), behind > 0 && _jsxs(Text, { color: colors.warning, children: [behind, " behind"] })] })), hasConflicts && (_jsx(Box, { children: _jsx(Text, { color: colors.error, children: "Conflicts detected!" }) })), (stagedCount > 0 || modifiedCount > 0 || untrackedCount > 0) && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Changes: " }), stagedCount > 0 && (_jsxs(Text, { color: colors.success, children: [stagedCount, " staged"] })), stagedCount > 0 && (modifiedCount > 0 || untrackedCount > 0) && (_jsx(Text, { color: colors.secondary, children: ", " })), modifiedCount > 0 && (_jsxs(Text, { color: colors.warning, children: [modifiedCount, " modified"] })), modifiedCount > 0 && untrackedCount > 0 && (_jsx(Text, { color: colors.secondary, children: ", " })), untrackedCount > 0 && (_jsxs(Text, { color: colors.text, children: [untrackedCount, " untracked"] }))] })), stagedCount === 0 &&
                modifiedCount === 0 &&
                untrackedCount === 0 &&
                !hasConflicts &&
                branch && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.success, children: "\u2713 Working tree clean" }) }))] }));
}
const formatter = (_args, result) => {
    return _jsx(GitStatusFormatter, { result: result });
};
// ============================================================================
// Export
// ============================================================================
export const gitStatusTool = {
    name: 'git_status',
    tool: gitStatusCoreTool,
    formatter,
    readOnly: true,
};
//# sourceMappingURL=git-status.js.map