import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import { TOOL_NAME, TOOL_SCHEMA, TOOL_DESCRIPTION } from "./chainOfDraftParams.js";
import { logger } from "../utils/logging.js";

interface ThoughtData {
    // Required fields
    reasoning_chain: string[];
    next_step_needed: boolean;
    draft_number: number;
    total_drafts: number;

    // Optional fields
    is_critique?: boolean;
    critique_focus?: string;
    revision_instructions?: string;
    step_to_review?: number;
    is_final_draft: boolean;  // This has a default of false
}

interface SessionState {
    thoughtHistory: ThoughtData[];
    branches: Record<string, ThoughtData[]>;
}

const sessions = new Map<string, SessionState>();

export const chainOfDraftTool = (server: McpServer): void => {
    const getOrCreateSession = (sessionId: string): SessionState => {
        if (!sessions.has(sessionId)) {
            sessions.set(sessionId, {
                thoughtHistory: [],
                branches: {}
            });
        }
        return sessions.get(sessionId)!;
    };

    const processThoughtRequest = async (input: unknown, sessionId: string) => {
        try {
            const session = getOrCreateSession(sessionId);
            const validatedInput = validateThoughtData(input);
            if (!validatedInput) {
                throw new McpError(ErrorCode.InvalidParams, "Invalid thought data");
            }

            // Validate draft progression
            if (validatedInput.draft_number > validatedInput.total_drafts) {
                validatedInput.total_drafts = validatedInput.draft_number;
            }

            // Store the thought in session history
            session.thoughtHistory.push(validatedInput);

            // Handle branching if specified
            if (validatedInput.step_to_review !== undefined) {
                const branchId = `branch_${validatedInput.draft_number}_${validatedInput.step_to_review}`;
                if (!session.branches[branchId]) {
                    session.branches[branchId] = [];
                }
                session.branches[branchId].push(validatedInput);
            }

            // Format response
            return {
                content: [{
                    type: "text",
                    text: JSON.stringify({
                        draftNumber: validatedInput.draft_number,
                        totalDrafts: validatedInput.total_drafts,
                        nextStepNeeded: validatedInput.next_step_needed,
                        isCritique: validatedInput.is_critique,
                        critiqueFocus: validatedInput.critique_focus,
                        revisionInstructions: validatedInput.revision_instructions,
                        stepToReview: validatedInput.step_to_review,
                        isFinalDraft: validatedInput.is_final_draft,
                        branches: Object.keys(session.branches),
                        thoughtHistoryLength: session.thoughtHistory.length
                    }, null, 2)
                }]
            };
        } catch (error) {
            if (error instanceof McpError) {
                throw error;
            }
            throw new McpError(
                ErrorCode.InternalError,
                error instanceof Error ? error.message : String(error)
            );
        }
    };

    server.tool(
        TOOL_NAME,
        TOOL_DESCRIPTION,
        TOOL_SCHEMA,
        async (args, extra) => {
            const sessionId = extra.sessionId || 'default';
            return {
                content: [{
                    type: "text" as const,
                    text: JSON.stringify(await processThoughtRequest(args, sessionId))
                }]
            };
        }
    );
}

// const TOOL_DESCRIPTION = `
//     A tool for generating and refining reasoning chains using Chain of Draft (CoD).

// This tool enhances Chain of Thought (CoT) prompting by incorporating iterative critique and revision of the generated reasoning steps, leading to more accurate and robust conclusions.

// When to use this tool:
// -   Complex reasoning tasks where accuracy and logical flow are critical.
// -   Problems that require breaking down into multiple steps, and where each step needs careful scrutiny.
// -   Situations where the initial reasoning chain might contain errors, inconsistencies, or gaps.
// -   For tasks like solving math problems, logical puzzles, and detailed analysis of complex information.

// Key features:
// -   Generates an initial chain of thought.
// -   Allows for iterative critique and revision of individual steps or the entire chain.
// -   Enables focusing on specific aspects of the reasoning (e.g., logical validity, completeness, relevance).
// -   Provides parameters to control the CoT process, such as draft number, total drafts, and revision focus.
// -   Maintains context across iterations of the reasoning chain.

// Parameters explained:
// -   reasoning_chain: The current chain of thought, consisting of one or more reasoning steps.
// -   next_step_needed: True if another critique/revision cycle is needed.
// -   draft_number: The current draft number (starting from 1).
// -   total_drafts: The total number of draft/revision cycles planned.
// -   is_critique: Boolean indicating if the current step is a critique (true) or revision (false).
// -   critique_focus: Specifies the focus of the current critique (e.g., "logical validity", "completeness", "relevance", "clarity").
// -   revision_instructions: Specific instructions for the revision, based on the critique.
// -   step_to_revise: (Optional) If revising a specific step, the index or identifier of that step.

// You should:
// 1.  Start with an initial reasoning_chain and set total_drafts.
// 2.  Use is_critique to alternate between critique and revision steps.
// 3.  Specify critique_focus to guide the critique process.
// 4.  Provide detailed revision_instructions based on the critique.
// 5.  Use step_to_revise to target specific parts of the reasoning chain.
// 6.  Adjust total_drafts as needed based on the progress.
// 7.  Set next_step_needed to false only when the final reasoning_chain is complete and satisfactory.

// `;

const validateThoughtData = (input: unknown): ThoughtData | null => {
    const data = input as Record<string, unknown>;

    // Check only required fields first
    if (typeof data !== "object" || data === null ||
        !("reasoning_chain" in data) ||
        !("next_step_needed" in data) ||
        !("draft_number" in data) ||
        !("total_drafts" in data)) {
        throw new Error("Missing required fields");
    }

    // Validate types and create return object
    const thoughtData: ThoughtData = {
        reasoning_chain: Array.isArray(data.reasoning_chain) ? data.reasoning_chain : [],
        next_step_needed: Boolean(data.next_step_needed),
        draft_number: Number(data.draft_number),
        total_drafts: Number(data.total_drafts),
        is_final_draft: Boolean(data.is_final_draft ?? false)
    };

    // Optional fields
    if ("is_critique" in data) thoughtData.is_critique = Boolean(data.is_critique);
    if ("critique_focus" in data) thoughtData.critique_focus = String(data.critique_focus);
    if ("revision_instructions" in data) thoughtData.revision_instructions = String(data.revision_instructions);
    if ("step_to_review" in data) thoughtData.step_to_review = Number(data.step_to_review);

    // Validate the data
    if (!Array.isArray(thoughtData.reasoning_chain) || thoughtData.reasoning_chain.length === 0) {
        throw new Error("Invalid reasoning chain");
    }

    if (thoughtData.draft_number <= 0) {
        throw new Error("Draft number must be positive");
    }

    if (thoughtData.total_drafts <= 0) {
        throw new Error("Total drafts must be positive");
    }

    if (thoughtData.draft_number > thoughtData.total_drafts) {
        throw new Error("Draft number cannot exceed total drafts");
    }

    // Validate critique-specific fields
    if (thoughtData.is_critique && !thoughtData.critique_focus) {
        throw new Error("Critique focus required when is_critique is true");
    }

    return thoughtData;
}
const formatThought = (thought: ThoughtData): string => {
    return JSON.stringify({
        thoughtNumber: thought.draft_number,
        thought: thought.reasoning_chain
    });
}

const processThought = (input: unknown): { content: Array<{ type: string; text: string }>; isError?: boolean } => {
    try {
        const validatedInput = validateThoughtData(input);
        if (!validatedInput) {
            throw new Error("Invalid thought data");
        }

        // make sure we have a valid thought number
        if (validatedInput.draft_number <= 0) {
            throw new Error("Invalid draft number");
        }

        // make sure we have a valid total drafts
        if (validatedInput.total_drafts <= 0) {
            throw new Error("Invalid total drafts");
        }

        // make sure we have a valid reasoning chain
        if (!Array.isArray(validatedInput.reasoning_chain) || validatedInput.reasoning_chain.length === 0) {
            throw new Error("Invalid reasoning chain");
        }

        // make sure we have a valid next step needed
        if (typeof validatedInput.next_step_needed !== "boolean") {
            throw new Error("Invalid next step needed");
        }

        // make sure we have a valid critique focus
        if (validatedInput.is_critique && !validatedInput.critique_focus) {
            throw new Error("Invalid critique focus");
        }

        // make sure we have a valid revision instructions
        if (validatedInput.is_critique && !validatedInput.revision_instructions) {
            throw new Error("Invalid revision instructions");
        }

        // make sure we have a valid step to review
        if (validatedInput.step_to_review && (typeof validatedInput.step_to_review !== "number" || validatedInput.step_to_review < 0)) {
            throw new Error("Invalid step to review");
        }

        // make sure we have a valid is final draft
        if (typeof validatedInput.is_final_draft !== "boolean") {
            throw new Error("Invalid is final draft");
        }

        // make sure the current ask is not greater than the total drafts
        if (validatedInput.draft_number > validatedInput.total_drafts) {
            throw new Error("Current draft number is greater than the total drafts");
        }

        const formattedThought = formatThought(validatedInput);
        logger.error(formattedThought);

        return {
            content: [{
                type: "text",
                text: JSON.stringify({
                    thoughtNumber: validatedInput.draft_number,
                    thought: formattedThought
                })
            }]
        }


    } catch (error) {
        return {
            content: [{
                type: "text",
                text: JSON.stringify({
                    error: error instanceof Error ? error.message : String(error),
                    status: 'failed'
                }, null, 2)
            }],
            isError: true
        };
    }
}

const clearSession = (sessionId: string): void => {
    sessions.delete(sessionId);
};

const pruneOldSessions = (): void => {
    // Add logic to remove sessions older than X time
    // This prevents memory leaks
};