import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Git Commit Tool
 *
 * Create a commit with the staged changes.
 */
import { Box, Text } from 'ink';
import React from 'react';
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, getDiffStats, hasStagedChanges, isLastCommitPushed, parseGitStatus, } from './utils.js';
// ============================================================================
// Preview (for formatter before execution)
// ============================================================================
async function getCommitPreview(args) {
    // Get staged files
    const statusOutput = await execGit(['status', '--porcelain']);
    const { staged } = parseGitStatus(statusOutput);
    // Get diff stats
    const stats = await getDiffStats(true);
    for (const file of staged) {
        const fileStats = stats.get(file.path);
        if (fileStats) {
            file.additions = fileStats.additions;
            file.deletions = fileStats.deletions;
        }
    }
    const totalAdditions = staged.reduce((sum, f) => sum + f.additions, 0);
    const totalDeletions = staged.reduce((sum, f) => sum + f.deletions, 0);
    // Check if amending a pushed commit
    let amendWarning = null;
    if (args.amend) {
        const pushed = await isLastCommitPushed();
        if (pushed) {
            amendWarning = 'Warning: Amending a commit that has already been pushed!';
        }
    }
    return { staged, totalAdditions, totalDeletions, amendWarning };
}
// ============================================================================
// Execution
// ============================================================================
const executeGitCommit = async (args) => {
    try {
        // Check for staged changes (unless amending)
        if (!args.amend) {
            const hasStaged = await hasStagedChanges();
            if (!hasStaged) {
                return 'Error: No staged changes to commit. Use git_add to stage changes first.';
            }
        }
        // Build commit message
        let fullMessage = args.message;
        if (args.body) {
            fullMessage = `${args.message}\n\n${args.body}`;
        }
        // Build git command
        const gitArgs = ['commit', '-m', fullMessage];
        if (args.amend) {
            gitArgs.push('--amend');
        }
        if (args.noVerify) {
            gitArgs.push('--no-verify');
        }
        const output = await execGit(gitArgs);
        // Parse the output to get commit info
        const lines = [];
        // Extract commit hash if present
        const hashMatch = output.match(/\[[\w-]+\s+([a-f0-9]+)\]/);
        if (hashMatch) {
            lines.push(`Commit created: ${hashMatch[1]}`);
        }
        else {
            lines.push('Commit created successfully.');
        }
        lines.push('');
        lines.push(`Message: ${args.message}`);
        if (args.body) {
            lines.push(`Body: ${args.body.substring(0, 100)}${args.body.length > 100 ? '...' : ''}`);
        }
        if (args.amend) {
            lines.push('');
            lines.push('(Amended previous commit)');
        }
        return lines.join('\n');
    }
    catch (error) {
        return `Error: ${formatError(error)}`;
    }
};
// ============================================================================
// Tool Definition
// ============================================================================
const gitCommitCoreTool = tool({
    description: 'Create a git commit with staged changes. Requires a commit message. Use body for extended description, amend to modify the last commit.',
    inputSchema: jsonSchema({
        type: 'object',
        properties: {
            message: {
                type: 'string',
                description: 'The commit message (required)',
            },
            body: {
                type: 'string',
                description: 'Extended description (will be separated by blank line)',
            },
            amend: {
                type: 'boolean',
                description: 'Amend the previous commit instead of creating a new one',
            },
            noVerify: {
                type: 'boolean',
                description: 'Skip pre-commit and commit-msg hooks',
            },
        },
        required: ['message'],
    }),
    execute: async (args, _options) => {
        return await executeGitCommit(args);
    },
});
// ============================================================================
// Formatter
// ============================================================================
function GitCommitFormatter({ args, result, }) {
    const boxWidth = useTerminalWidth();
    const { colors } = useTheme();
    const [preview, setPreview] = React.useState(null);
    // Load preview before execution
    React.useEffect(() => {
        if (!result) {
            getCommitPreview(args)
                .then(setPreview)
                .catch(() => { });
        }
    }, [args, result]);
    const stagedCount = preview?.staged.length || 0;
    const additions = preview?.totalAdditions || 0;
    const deletions = preview?.totalDeletions || 0;
    return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, width: boxWidth, children: [_jsx(Text, { color: colors.tool, children: "\u2692 git_commit" }), !result && stagedCount > 0 && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Staged: " }), _jsxs(Text, { color: colors.text, children: [stagedCount, " files "] }), _jsxs(Text, { color: colors.success, children: ["(+", additions] }), _jsx(Text, { color: colors.text, children: ", " }), _jsxs(Text, { color: colors.error, children: ["-", deletions] }), _jsx(Text, { color: colors.text, children: ")" })] })), args.amend && (_jsx(Box, { children: _jsx(Text, { color: colors.warning, children: "Amending previous commit" }) })), preview?.amendWarning && (_jsx(Box, { children: _jsx(Text, { color: colors.error, children: preview.amendWarning }) })), args.noVerify && (_jsxs(Box, { children: [_jsx(Text, { color: colors.secondary, children: "Hooks: " }), _jsx(Text, { color: colors.warning, children: "skipped" })] })), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.secondary, children: "Message:" }), _jsx(Box, { marginLeft: 2, flexShrink: 1, children: _jsx(Text, { wrap: "truncate-end", color: colors.primary, children: args.message }) })] }), args.body && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.secondary, children: "Body:" }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: colors.text, children: args.body.length > 100
                                ? `${args.body.substring(0, 100)}...`
                                : args.body }) })] })), result?.includes('Commit created') && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.success, children: "\u2713 Commit created successfully" }) })), result?.includes('Error:') && (_jsx(Box, { children: _jsx(Text, { color: colors.error, children: result }) }))] }));
}
const formatter = (args, result) => {
    return _jsx(GitCommitFormatter, { args: args, result: result });
};
// ============================================================================
// Validator
// ============================================================================
const validator = async (args) => {
    if (!args.message || args.message.trim().length === 0) {
        return { valid: false, error: 'Commit message cannot be empty' };
    }
    // Check for staged changes (unless amending)
    if (!args.amend) {
        const hasStaged = await hasStagedChanges();
        if (!hasStaged) {
            return {
                valid: false,
                error: 'No staged changes. Use git_add to stage changes first.',
            };
        }
    }
    return { valid: true };
};
// ============================================================================
// Export
// ============================================================================
export const gitCommitTool = {
    name: 'git_commit',
    tool: gitCommitCoreTool,
    formatter,
    validator,
    // ALWAYS_APPROVE - user should see the commit message before creation
    approval: true,
};
//# sourceMappingURL=git-commit.js.map