import { composeSystemPrompt } from './system-prompt-composer.js';
import {
  createAgentsMdSection,
  createCapabilitySections,
  createClaudeMdSection,
  createPermissionSection,
  createPersonaSection,
  createProjectMemorySection,
  createProjectSection,
  createResponseLanguageSection,
  createSelfVerificationSection,
  createTaskContextSection,
  createToolDescriptionSection,
  createWorkingDirectorySection,
} from './system-prompt-section-providers.js';

import type { IProjectInfo } from './project-detector.js';
import type { ISystemPromptSection } from './system-prompt-types.js';
import type { ICapabilityDescriptor } from '../capabilities/types.js';
import type { TPermissionMode } from '@robota-sdk/agent-core';

export interface ISystemPromptParams {
  /**
   * Preset persona block (portable personality/behaviour). When set and non-blank it is
   * composed as a `source: 'persona'` section with priority 5; empty/undefined adds no section.
   */
  persona?: string;
  /**
   * PRESET-017: when true, a concise verify-before-done directive is composed as a
   * `source: 'self-verification'` section with priority 6; false/undefined adds no section.
   */
  selfVerification?: boolean;
  /** Concatenated AGENTS.md content (may be empty string) */
  agentsMd: string;
  /** Concatenated CLAUDE.md content (may be empty string) */
  claudeMd: string;
  /** Startup project memory index loaded from .robota/memory/MEMORY.md */
  memoryMd?: string;
  /** Formatted active task context loaded from .agents/tasks/*.md */
  taskContext?: string;
  /** Human-readable tool descriptions, one per entry */
  toolDescriptions: string[];
  /** Active permission mode — the value the permission gate enforces */
  permissionMode: TPermissionMode;
  /** Detected project metadata */
  projectInfo: IProjectInfo;
  /** Current working directory */
  cwd?: string;
  /** Response language code (e.g., "ko", "en"). If set, AI must respond in this language. */
  language?: string;
  /** Discovered skills to expose in the system prompt */
  skills?: Array<{ name: string; description: string; disableModelInvocation?: boolean }>;
  /** Discovered agents to expose in the system prompt */
  agents?: Array<{ name: string; description: string }>;
  /** Command descriptors to expose to the model */
  commandDescriptors?: ICapabilityDescriptor[];
}

function appendOptionalSection(
  sections: ISystemPromptSection[],
  section: ISystemPromptSection | undefined,
): void {
  if (section !== undefined) sections.push(section);
}

function mapSkillDescriptors(
  skills: NonNullable<ISystemPromptParams['skills']>,
): ICapabilityDescriptor[] {
  return skills.map((skill) => ({
    name: skill.name,
    kind: 'skill',
    description: skill.description,
    userInvocable: true,
    modelInvocable: skill.disableModelInvocation !== true,
  }));
}

function mapAgentDescriptors(
  agents: NonNullable<ISystemPromptParams['agents']>,
): ICapabilityDescriptor[] {
  return agents.map((agent) => ({
    name: agent.name,
    kind: 'agent',
    description: agent.description,
    userInvocable: false,
    modelInvocable: true,
    safety: 'background-agent',
  }));
}

function buildCapabilityDescriptors(params: ISystemPromptParams): ICapabilityDescriptor[] {
  return [
    ...(params.commandDescriptors ?? []),
    ...(params.skills ? mapSkillDescriptors(params.skills) : []),
    ...(params.agents ? mapAgentDescriptors(params.agents) : []),
  ];
}

export function buildSystemPrompt(params: ISystemPromptParams): string {
  const sections: ISystemPromptSection[] = [];

  appendOptionalSection(
    sections,
    params.persona !== undefined && params.persona.trim().length > 0
      ? createPersonaSection(params.persona)
      : undefined,
  );
  appendOptionalSection(
    sections,
    params.selfVerification === true ? createSelfVerificationSection() : undefined,
  );
  appendOptionalSection(sections, createAgentsMdSection(params.agentsMd));
  appendOptionalSection(sections, createClaudeMdSection(params.claudeMd));
  appendOptionalSection(sections, createProjectMemorySection(params.memoryMd));
  appendOptionalSection(sections, createTaskContextSection(params.taskContext));
  appendOptionalSection(sections, createWorkingDirectorySection(params.cwd));
  sections.push(createProjectSection(params.projectInfo));
  appendOptionalSection(sections, createResponseLanguageSection(params.language));
  sections.push(createPermissionSection(params.permissionMode));
  appendOptionalSection(sections, createToolDescriptionSection(params.toolDescriptions));
  sections.push(...createCapabilitySections(buildCapabilityDescriptors(params)));

  return composeSystemPrompt(sections);
}
