import * as vscode from "vscode";
import * as path from "path";
import { collectDiagnostics } from "../diagnostics.js";

const COMMAND_ID = "acurity.validateTxtFolder";

function formatSeverity(severity) {
    if (severity === vscode.DiagnosticSeverity.Error) {
        return "error";
    }
    if (severity === vscode.DiagnosticSeverity.Warning) {
        return "warning";
    }
    if (severity === vscode.DiagnosticSeverity.Information) {
        return "information";
    }
    if (severity === vscode.DiagnosticSeverity.Hint) {
        return "hint";
    }
    return String(severity);
}

function safeRelativePath(folderFsPath, fileFsPath) {
    const relative = path.relative(folderFsPath, fileFsPath);
    return relative && !relative.startsWith("..") ? relative.replace(/\\/g, "/") : fileFsPath;
}

function buildDefaultReportFileName() {
    const now = new Date();
    const pad = (value) => String(value).padStart(2, "0");
    const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
    return `acurity-validation-report-${stamp}.json`;
}

async function chooseTargetFolder() {
    const selection = await vscode.window.showOpenDialog({
        canSelectFiles: false,
        canSelectFolders: true,
        canSelectMany: false,
        openLabel: "Validate This Folder"
    });

    return selection && selection.length > 0 ? selection[0] : null;
}

async function chooseOutputFile(defaultFolderUri) {
    const defaultUri = vscode.Uri.joinPath(defaultFolderUri, buildDefaultReportFileName());

    return vscode.window.showSaveDialog({
        saveLabel: "Save Validation Report",
        defaultUri,
        filters: {
            "JSON": ["json"]
        }
    });
}

function summarizeDiagnostics(fileResults) {
    const totals = {
        filesScanned: fileResults.length,
        filesWithDiagnostics: 0,
        diagnosticCount: 0,
        severity: {
            error: 0,
            warning: 0,
            information: 0,
            hint: 0
        },
        byMessageId: {}
    };

    for (const fileResult of fileResults) {
        if (fileResult.diagnosticCount > 0) {
            totals.filesWithDiagnostics += 1;
        }

        totals.diagnosticCount += fileResult.diagnosticCount;

        for (const diagnostic of fileResult.diagnostics) {
            totals.severity[diagnostic.severity] = (totals.severity[diagnostic.severity] || 0) + 1;

            if (diagnostic.messageId) {
                totals.byMessageId[diagnostic.messageId] = (totals.byMessageId[diagnostic.messageId] || 0) + 1;
            }
        }
    }

    return totals;
}

async function runBatchValidation() {
    const folderUri = await chooseTargetFolder();
    if (!folderUri) {
        return;
    }

    const outputUri = await chooseOutputFile(folderUri);
    if (!outputUri) {
        return;
    }

    const txtFiles = await vscode.workspace.findFiles(
        new vscode.RelativePattern(folderUri, "**/*.{txt,TXT}"),
        "**/{node_modules,.git}/**"
    );

    if (txtFiles.length === 0) {
        await vscode.window.showInformationMessage("No .txt/.TXT files found in the selected folder.");
        return;
    }

    const fileResults = [];

    await vscode.window.withProgress(
        {
            location: vscode.ProgressLocation.Notification,
            title: `Acurity: Validating ${txtFiles.length} TXT files`,
            cancellable: true
        },
        async (progress, token) => {
            for (let index = 0; index < txtFiles.length; index += 1) {
                if (token.isCancellationRequested) {
                    break;
                }

                const fileUri = txtFiles[index];
                const relativePath = safeRelativePath(folderUri.fsPath, fileUri.fsPath);

                progress.report({
                    message: `${index + 1}/${txtFiles.length} ${relativePath}`,
                    increment: 100 / txtFiles.length
                });

                const document = await vscode.workspace.openTextDocument(fileUri);
                const diagnostics = await collectDiagnostics(document);

                const normalizedDiagnostics = diagnostics.map((diagnostic) => ({
                    severity: formatSeverity(diagnostic.severity),
                    messageId: diagnostic.data?.messageId || null,
                    ruleId: diagnostic.data?.ruleId || null,
                    message: diagnostic.message,
                    line: diagnostic.range.start.line + 1,
                    column: diagnostic.range.start.character + 1,
                    endLine: diagnostic.range.end.line + 1,
                    endColumn: diagnostic.range.end.character + 1,
                    params: diagnostic.data?.params || null
                }));

                fileResults.push({
                    file: relativePath,
                    diagnosticCount: normalizedDiagnostics.length,
                    diagnostics: normalizedDiagnostics
                });
            }
        }
    );

    const summary = summarizeDiagnostics(fileResults);
    const report = {
        generatedAt: new Date().toISOString(),
        folder: folderUri.fsPath,
        reportVersion: "1.0",
        summary,
        files: fileResults
    };

    const reportContent = JSON.stringify(report, null, 2);
    await vscode.workspace.fs.writeFile(outputUri, Buffer.from(reportContent, "utf8"));

    const reportDoc = await vscode.workspace.openTextDocument(outputUri);
    await vscode.window.showTextDocument(reportDoc, { preview: false });

    await vscode.window.showInformationMessage(
        `Acurity validation complete: ${summary.filesScanned} files scanned, ${summary.diagnosticCount} diagnostics. Report saved to ${outputUri.fsPath}`
    );
}

function registerBatchValidateTxtFolderCommand(context) {
    const disposable = vscode.commands.registerCommand(COMMAND_ID, async () => {
        try {
            await runBatchValidation();
        } catch (error) {
            const message = error && error.message ? error.message : String(error);
            vscode.window.showErrorMessage(`Acurity batch validation failed: ${message}`);
        }
    });

    context.subscriptions.push(disposable);
}

export {
    registerBatchValidateTxtFolderCommand
};
