import { readFileSync, existsSync } from 'fs';
import { resolve } from 'path';
import type { ContextLevel, TruthfulnessMode } from '../config/schema.js';
import { getTruthfulnessGuidance } from '../backends/native/guardrails.js';

/** Ordered list of prompt template files to look for. */
const PROMPT_FILES = [
  { name: 'SOUL.md', section: 'Identity', required: false },
  { name: 'AGENTS.md', section: 'Agent Instructions', required: false },
  { name: 'IDENTITY.md', section: 'Identity Customization', required: false },
  { name: 'USER.md', section: 'User Context', required: false },
  { name: 'TOOLS.md', section: 'Tool Instructions', required: false },
] as const;

export interface PromptTemplateConfig {
  /** Directories to search for template files, in priority order. */
  searchDirs: string[];
  /** Additional sections to inject (e.g., from config). */
  extraSections?: Array<{ name: string; content: string }>;
  /** Prompt context depth. Defaults to normal. */
  contextLevel?: ContextLevel;
  /** Truthfulness enforcement mode. Defaults to standard. */
  truthfulnessMode?: TruthfulnessMode;
}

export interface PromptTemplateResult {
  /** The assembled system prompt. */
  prompt: string;
  /** Which files were loaded. */
  loadedFiles: string[];
}

/**
 * Assemble a system prompt from multiple template files.
 *
 * Searches `searchDirs` in order for each template file.
 * First match wins — a file found in an earlier directory takes precedence.
 * Sections are assembled in the order defined in PROMPT_FILES.
 */
export function assembleSystemPrompt(config: PromptTemplateConfig): PromptTemplateResult {
  const level = config.contextLevel ?? 'normal';
  const truthfulnessMode = config.truthfulnessMode ?? 'standard';
  const includeAllTemplates = level !== 'minimal';
  const includeExtraSections = level !== 'minimal';
  const includeDebugSection = level === 'debug';
  const includeTruthfulness = truthfulnessMode === 'strict' || truthfulnessMode === 'standard';

  const sections: string[] = [];
  const loadedFiles: string[] = [];

  for (const { name, section } of PROMPT_FILES) {
    if (!includeAllTemplates && name !== 'SOUL.md') {
      continue;
    }

    for (const dir of config.searchDirs) {
      const filePath = resolve(dir, name);
      if (existsSync(filePath)) {
        const content = readFileSync(filePath, 'utf-8').trim();
        if (content) {
          // SOUL.md is special — it's the base identity, no section header
          if (name === 'SOUL.md') {
            sections.push(content);
          } else {
            sections.push(`# ${section}\n\n${content}`);
          }
          loadedFiles.push(filePath);
        }
        break; // First match wins for this file
      }
    }
  }

  // Add extra sections
  if (includeExtraSections && config.extraSections) {
    for (const { name, content } of config.extraSections) {
      if (content.trim()) {
        sections.push(`# ${name}\n\n${content.trim()}`);
      }
    }
  }

  // Inject truthfulness guidance (for strict and standard modes)
  if (includeTruthfulness) {
    sections.push(getTruthfulnessGuidance(truthfulnessMode));
  }

  // Inject current date/time as runtime context
  const now = new Date();
  const dateStr = now.toLocaleDateString('en-US', {
    weekday: 'long',
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });
  const timeStr = now.toLocaleTimeString('en-US', {
    hour: '2-digit',
    minute: '2-digit',
    timeZoneName: 'short',
    hour12: false,
  });
  const runtimeContext = `# Runtime Context\n\nCurrent date: ${dateStr}\nCurrent time: ${timeStr}`;
  sections.push(runtimeContext);

  if (includeDebugSection) {
    const loadedFilesList = loadedFiles.length > 0
      ? loadedFiles.map((filePath) => `- ${filePath}`).join('\n')
      : '- none';
    const searchDirsList = config.searchDirs.length > 0
      ? config.searchDirs.map((dir) => `- ${dir}`).join('\n')
      : '- none';

    sections.push(
      `# Prompt Debug\n\nContext level: ${level}\n\nLoaded files:\n${loadedFilesList}\n\nDirectory resolution notes:\n${searchDirsList}\n- First match wins per template file.`,
    );
  }

  // Fallback when no prompt template files were found.
  if (loadedFiles.length === 0) {
    const truthfulnessSection = includeTruthfulness
      ? `${getTruthfulnessGuidance(truthfulnessMode)}\n\n`
      : '';
    return {
      prompt: `You are Flynn, a helpful personal AI assistant. Be direct, concise, and helpful. Use markdown when it improves readability.\n\n${truthfulnessSection}${runtimeContext}`,
      loadedFiles: [],
    };
  }

  return {
    prompt: sections.join('\n\n'),
    loadedFiles,
  };
}
