/**
 * Prompt Builder for Harmony MCP Server
 *
 * Generates AI-ready prompts from Harmony cards with role-based framing,
 * context extraction, and variant-specific instructions.
 */
// Label name to category mapping
const LABEL_CATEGORY_MAP = {
    bug: "bug",
    fix: "bug",
    hotfix: "bug",
    defect: "bug",
    issue: "bug",
    error: "bug",
    feature: "feature",
    enhancement: "feature",
    improvement: "feature",
    new: "feature",
    design: "design",
    ui: "design",
    ux: "design",
    frontend: "design",
    styling: "design",
    review: "review",
    "code review": "review",
    pr: "review",
    feedback: "review",
    onboarding: "onboarding",
    documentation: "onboarding",
    docs: "onboarding",
    guide: "onboarding",
    tutorial: "onboarding",
    epic: "epic",
    initiative: "epic",
    project: "epic",
    milestone: "epic",
};
// Default role framings
const DEFAULT_ROLE_FRAMINGS = {
    bug: {
        category: "bug",
        role: "Senior QA Engineer and Software Developer",
        perspective: "You are investigating and fixing a bug report.",
        focus: [
            "Root cause analysis",
            "Steps to reproduce",
            "Impact assessment",
            "Fix implementation",
            "Regression prevention",
            "Test cases to prevent recurrence",
        ],
        outputSuggestions: [
            "Bug triage summary",
            "Root cause explanation",
            "Fix implementation plan",
            "Test cases",
        ],
    },
    feature: {
        category: "feature",
        role: "Product Engineer",
        perspective: "You are implementing a new feature or enhancement.",
        focus: [
            "User requirements",
            "Technical specification",
            "Implementation approach",
            "Edge cases",
            "Acceptance criteria",
            "Integration points",
        ],
        outputSuggestions: [
            "Technical specification",
            "Implementation tasks",
            "Acceptance criteria checklist",
            "API design",
        ],
    },
    design: {
        category: "design",
        role: "UX Designer and Frontend Developer",
        perspective: "You are designing and implementing a user interface.",
        focus: [
            "User experience flow",
            "Visual design consistency",
            "Accessibility (WCAG)",
            "Responsive behavior",
            "Component architecture",
            "Interaction patterns",
        ],
        outputSuggestions: [
            "User flow diagram",
            "Component specifications",
            "Accessibility checklist",
            "Responsive breakpoints",
        ],
    },
    review: {
        category: "review",
        role: "Code Reviewer and Technical Lead",
        perspective: "You are reviewing code for quality, correctness, and maintainability.",
        focus: [
            "Code correctness",
            "Performance implications",
            "Security considerations",
            "Testing coverage",
            "Documentation",
            "Best practices adherence",
        ],
        outputSuggestions: [
            "Review checklist",
            "Suggested improvements",
            "Test scenarios",
            "Security audit",
        ],
    },
    onboarding: {
        category: "onboarding",
        role: "Technical Writer and Developer Advocate",
        perspective: "You are creating documentation or onboarding materials.",
        focus: [
            "Clear step-by-step instructions",
            "Prerequisites and setup",
            "Common pitfalls",
            "Examples and use cases",
            "Troubleshooting guide",
            "Related resources",
        ],
        outputSuggestions: [
            "Getting started guide",
            "Step-by-step tutorial",
            "FAQ section",
            "Troubleshooting guide",
        ],
    },
    epic: {
        category: "epic",
        role: "Technical Project Manager and Architect",
        perspective: "You are planning and coordinating a large initiative.",
        focus: [
            "Scope definition",
            "Task breakdown",
            "Dependencies",
            "Risk assessment",
            "Timeline considerations",
            "Success metrics",
        ],
        outputSuggestions: [
            "Epic breakdown into stories",
            "Dependency graph",
            "Risk mitigation plan",
            "Success criteria",
        ],
    },
    custom: {
        category: "custom",
        role: "Software Engineer",
        perspective: "You are working on a software task.",
        focus: [
            "Understanding requirements",
            "Implementation approach",
            "Quality considerations",
            "Testing strategy",
        ],
        outputSuggestions: [
            "Implementation plan",
            "Technical notes",
            "Task checklist",
        ],
    },
};
// Variant-specific instructions
const VARIANT_INSTRUCTIONS = {
    analysis: `ANALYSIS MODE: Analyze this task thoroughly. Identify requirements, constraints, edge cases, and potential challenges. Do NOT implement anything yet - focus on understanding and planning.`,
    draft: `DRAFT MODE: Create a detailed implementation plan with code structure, key decisions, and approach. Include pseudocode or skeleton code where helpful. This is for review before full implementation.`,
    execute: `EXECUTE MODE: Implement this task completely. Write production-ready code following best practices. Include necessary tests and documentation.`,
};
/**
 * Infer category from labels
 */
export function inferCategoryFromLabels(labels) {
    for (const label of labels) {
        const normalizedName = label.name.toLowerCase().trim();
        if (LABEL_CATEGORY_MAP[normalizedName]) {
            return LABEL_CATEGORY_MAP[normalizedName];
        }
        for (const [key, category] of Object.entries(LABEL_CATEGORY_MAP)) {
            if (normalizedName.includes(key) || key.includes(normalizedName)) {
                return category;
            }
        }
    }
    return "custom";
}
/**
 * Get role framing for a category
 */
export function getRoleFraming(category) {
    return DEFAULT_ROLE_FRAMINGS[category];
}
/**
 * Estimate token count (rough approximation: 1 token per 4 chars)
 */
function estimateTokens(text) {
    return Math.ceil(text.length / 4);
}
/**
 * Format subtasks for prompt
 */
function formatSubtasks(subtasks) {
    if (subtasks.length === 0)
        return "";
    const completed = subtasks.filter((s) => s.completed).length;
    const lines = subtasks.map((s) => `  ${s.completed ? "[x]" : "[ ]"} ${s.title}`);
    return `\n## Subtasks (${completed}/${subtasks.length} completed)\n${lines.join("\n")}`;
}
/**
 * Format labels for prompt
 */
function formatLabels(labels) {
    if (labels.length === 0)
        return "";
    return `\n**Labels:** ${labels.map((l) => l.name).join(", ")}`;
}
/**
 * Format linked cards for prompt
 */
function formatLinkedCards(links) {
    if (!links || links.length === 0)
        return "";
    const lines = links.map((link) => {
        const prefix = link.direction === "outgoing" ? "->" : "<-";
        return `  ${prefix} #${link.target_card.short_id}: ${link.target_card.title} (${link.display_type})`;
    });
    return `\n## Related Cards\n${lines.join("\n")}`;
}
/**
 * Generate a prompt from a card
 */
export function generatePrompt(options) {
    const { card, column, variant, customConstraints, memories, assembledContext, assemblyId, } = options;
    // Merge context options with defaults
    const contextOpts = {
        includeTitle: true,
        includeDescription: true,
        includeLabels: true,
        includeSubtasks: true,
        includeActivity: false,
        includeAssignee: true,
        includeDueDate: true,
        includePriority: true,
        includeLinks: true,
        includeColumn: true,
        ...options.contextOptions,
    };
    const labels = card.labels || [];
    const subtasks = card.subtasks || [];
    const links = card.links || [];
    const category = inferCategoryFromLabels(labels);
    const roleFraming = getRoleFraming(category);
    // Build prompt sections
    const sections = [];
    // Role and perspective
    sections.push(`# Role: ${roleFraming.role}\n`);
    sections.push(roleFraming.perspective);
    sections.push("");
    // Variant instruction
    sections.push(VARIANT_INSTRUCTIONS[variant]);
    sections.push("");
    // Task header
    sections.push(`# Task: ${card.title}`);
    if (contextOpts.includeColumn && column) {
        sections.push(`**Status:** ${column.name}`);
    }
    if (contextOpts.includePriority) {
        sections.push(`**Priority:** ${card.priority}`);
    }
    if (contextOpts.includeDueDate && card.due_date) {
        sections.push(`**Due:** ${card.due_date}`);
    }
    if (contextOpts.includeAssignee && card.assignee) {
        sections.push(`**Assignee:** ${card.assignee.full_name || card.assignee.email}`);
    }
    // Labels
    if (contextOpts.includeLabels && labels.length > 0) {
        sections.push(formatLabels(labels));
    }
    // Description
    if (contextOpts.includeDescription && card.description) {
        sections.push(`\n## Description\n${card.description}`);
    }
    // Subtasks
    if (contextOpts.includeSubtasks && subtasks.length > 0) {
        sections.push(formatSubtasks(subtasks));
    }
    // Linked cards
    if (contextOpts.includeLinks && links.length > 0) {
        sections.push(formatLinkedCards(links));
    }
    // Focus areas
    sections.push(`\n## Focus Areas`);
    roleFraming.focus.forEach((f) => {
        sections.push(`- ${f}`);
    });
    sections.push(`- **Memory:** When you discover important domain knowledge, architectural decisions, or infrastructure details, store them via \`harmony_remember\`. Focus on durable knowledge that future agents would benefit from — not ephemeral task details (those are auto-extracted from your session).`);
    // Output suggestions
    sections.push(`\n## Suggested Outputs`);
    roleFraming.outputSuggestions.forEach((s) => {
        sections.push(`- ${s}`);
    });
    // Relevant memories from knowledge graph
    if (assembledContext) {
        // Use pre-assembled context from context assembly engine
        sections.push(`\n${assembledContext}`);
    }
    else if (memories && memories.length > 0) {
        // Fallback: legacy memory format
        sections.push(`\n## Relevant Memories`);
        sections.push(`*${memories.length} memories recalled from knowledge graph:*`);
        for (const memory of memories) {
            const tags = memory.tags.length > 0 ? ` [${memory.tags.join(", ")}]` : "";
            sections.push(`\n### ${memory.title} (${memory.type}, confidence: ${memory.confidence})${tags}`);
            sections.push(memory.content);
        }
    }
    // "One Thing" synthesis — highest-leverage next action
    const oneThingLine = synthesizeOneThing(card, subtasks, links, assembledContext);
    if (oneThingLine) {
        sections.push(`\n## Recommended Next Step\n${oneThingLine}`);
    }
    // Progress tracking (execute variant only)
    if (variant === "execute") {
        sections.push(`\n## Progress Tracking
Update your progress by calling \`harmony_update_agent_progress\` with \`currentTask\` describing what you're doing now:
- After exploring the codebase and understanding requirements (~20%)
- When you start implementing changes (~50%)
- When you move to testing or verification (~80%)
- When done, before ending the session (100%)

Keep \`currentTask\` specific (e.g., "Refactoring auth middleware" not "Working on card").`);
    }
    // Custom constraints
    if (customConstraints) {
        sections.push(`\n## Additional Instructions\n${customConstraints}`);
    }
    // Card reference footer
    sections.push(`\n---\n*Card #${card.short_id} | Generated for ${variant} mode*`);
    const prompt = sections.join("\n");
    const memoryCount = assembledContext
        ? (assembledContext.match(/^### /gm) || []).length
        : memories?.length || 0;
    return {
        prompt,
        variant,
        category,
        role: roleFraming.role,
        contextSummary: {
            hasDescription: !!card.description,
            labelCount: labels.length,
            subtaskCount: subtasks.length,
            completedSubtasks: subtasks.filter((s) => s.completed).length,
            linkedCardCount: links.length,
            memoryCount,
        },
        tokenEstimate: estimateTokens(prompt),
        ...(assemblyId && { assemblyId }),
    };
}
/**
 * Extract session insights from assembled context string.
 * Parses session summaries, blockers, and progress data.
 */
function extractSessionInsights(assembledContext) {
    const result = {
        lastSessionStatus: null,
        lastSessionTask: null,
        lastSessionProgress: null,
        blockers: [],
        procedureNextStep: null,
    };
    // Find the most recent session summary with status
    const sessionMatches = assembledContext.match(/### Session:.*?\n([\s\S]*?)(?=\n###|\n## |\n---|\n\*Assembly|$)/g);
    if (sessionMatches && sessionMatches.length > 0) {
        const latest = sessionMatches[0];
        if (/Completed work on/i.test(latest)) {
            result.lastSessionStatus = "completed";
        }
        else if (/Paused work on|status:\s*paused/i.test(latest)) {
            result.lastSessionStatus = "paused";
        }
        const taskMatch = latest.match(/Final task:\s*(.+)/);
        if (taskMatch)
            result.lastSessionTask = taskMatch[1].trim();
        const progressMatch = latest.match(/Progress:\s*(\d+)%/);
        if (progressMatch)
            result.lastSessionProgress = parseInt(progressMatch[1], 10);
    }
    // Extract blockers from context
    const blockerMatches = assembledContext.match(/(?:blocker|blocked by|blocking):\s*(.+)/gi);
    if (blockerMatches) {
        result.blockers = blockerMatches.map((m) => m.replace(/(?:blocker|blocked by|blocking):\s*/i, "").trim());
    }
    // Extract next procedure step (first uncompleted step)
    const stepMatches = assembledContext.match(/^\d+\.\s+(?!.*\*\*\[key step\]\*\*.*✓)(.+?)(?:\s*\*\*\[key step\]\*\*)?$/gm);
    if (stepMatches && stepMatches.length > 0) {
        result.procedureNextStep = stepMatches[0]
            .replace(/^\d+\.\s+/, "")
            .replace(/\s*\*\*\[key step\]\*\*.*$/, "")
            .trim();
    }
    return result;
}
/**
 * Synthesize the single highest-leverage next action from card state
 * and assembled context (session history, blockers, procedures).
 * Inspired by ArtemXTech's "One Thing" pattern in /recall.
 */
function synthesizeOneThing(card, subtasks, links, assembledContext) {
    // Priority 1: Card is already done
    if (card.done)
        return null;
    // Priority 2: Blocked by another card (via links)
    const blockers = links.filter((l) => l.display_type === "is_blocked_by" && l.direction === "incoming");
    if (blockers.length > 0) {
        const blocker = blockers[0];
        return `Unblock first: resolve #${blocker.target_card.short_id} "${blocker.target_card.title}" which is blocking this card.`;
    }
    // Extract session insights from assembled context
    const session = assembledContext
        ? extractSessionInsights(assembledContext)
        : null;
    // Priority 3: Blockers detected in session context
    if (session?.blockers && session.blockers.length > 0) {
        return `Resolve blocker: ${session.blockers[0]}`;
    }
    // Priority 4: Previous session was paused — resume where it left off
    if (session?.lastSessionStatus === "paused" && session.lastSessionTask) {
        const progress = session.lastSessionProgress
            ? ` (was ${session.lastSessionProgress}% complete)`
            : "";
        return `Resume previous session${progress}: "${session.lastSessionTask}".`;
    }
    // Priority 5: Has subtasks — find the first incomplete one
    if (subtasks.length > 0) {
        const completed = subtasks.filter((s) => s.completed).length;
        if (completed === subtasks.length) {
            return "All subtasks completed. Review the work and mark the card as done.";
        }
        const nextSubtask = subtasks.find((s) => !s.completed);
        if (nextSubtask) {
            return `Work on next subtask: "${nextSubtask.title}" (${completed}/${subtasks.length} done).`;
        }
    }
    // Priority 6: Procedure has a next step
    if (session?.procedureNextStep) {
        return `Follow procedure: ${session.procedureNextStep}`;
    }
    // Priority 7: Previous session completed — build on it
    if (session?.lastSessionStatus === "completed" && session.lastSessionTask) {
        return `Previous session completed ("${session.lastSessionTask}"). Review results and continue with remaining work.`;
    }
    // Priority 8: High/urgent priority with due date
    if (card.due_date &&
        (card.priority === "urgent" || card.priority === "high")) {
        return `High-priority task with deadline ${card.due_date}. Start implementation immediately.`;
    }
    // Priority 9: Has description — start working
    if (card.description) {
        return "Analyze the description, identify the approach, and begin implementation.";
    }
    // Fallback
    return null;
}
/**
 * Get all available categories
 */
export function getAvailableCategories() {
    return ["bug", "feature", "design", "review", "onboarding", "epic", "custom"];
}
/**
 * Get all available variants
 */
export function getAvailableVariants() {
    return ["analysis", "draft", "execute"];
}
