import fs from 'node:fs';
import path from 'node:path';
import { ROOT, WORKSPACE } from './paths.js';

const START_TAG = '<madarx_artifact>';
const END_TAG = '</madarx_artifact>';

const REDIRECT_PATTERNS = [
  /\bopen\s+(the\s+)?(link|url|file|path)\b/i,
  /\bview\s+(it|the result|the output)\s+(at|in)\b/i,
  /\bcan\s+find\s+it\s+at\b/i,
  /\bavailable\s+at\b/i,
  /\bserved\s+at\s+https?:\/\//i,
  /\bhttp:\/\/(?:127\.0\.0\.1|localhost):\d+\b/i,
];

export const HERMES_ARTIFACT_FORMAT_INSTRUCTIONS = `madarX artifact format contract:
- Your final answer MUST contain the dashboard artifact body between ${START_TAG} and ${END_TAG}.
- Inside ${START_TAG}, include the actual result content that should be displayed in the madarX artifact.
- Do NOT only tell the user to open a URL, file, localhost server, browser window, or workspace path.
- If you run a project, include the rendered result summary, command output, important logs, generated file paths, server URL if any, errors, and next steps inside the artifact body.
- If you generated a file, also paste its relevant contents or a faithful summary inside the artifact body.
- Text outside ${START_TAG} is ignored by madarX.`;

export function buildHermesArtifactPrompt(prompt) {
  return `${prompt}

${HERMES_ARTIFACT_FORMAT_INSTRUCTIONS}`;
}

function safeResolve(candidate) {
  if (!candidate) return null;
  const cleaned = String(candidate).replace(/[.,;:)]+$/g, '');
  const abs = cleaned.startsWith('/')
    ? path.resolve(cleaned)
    : path.resolve(ROOT, cleaned);
  const roots = [ROOT, WORKSPACE, path.dirname(ROOT)].map(p => path.resolve(p));
  if (!roots.some(root => abs === root || abs.startsWith(`${root}${path.sep}`))) return null;
  return abs;
}

function extractTaggedArtifact(response) {
  const text = String(response || '');
  const start = text.indexOf(START_TAG);
  const end = text.indexOf(END_TAG);
  if (start === -1 || end === -1 || end <= start) return '';
  return text.slice(start + START_TAG.length, end).trim();
}

function extractReferencedFiles(response) {
  const text = String(response || '');
  const matches = new Set();
  const patterns = [
    /(?:workspace|\.?\/workspace)\/[^\s'"`<>]+?\.(?:md|markdown|txt|html|json|log)/gi,
    /\/[^\s'"`<>]+?\.(?:md|markdown|txt|html|json|log)/gi,
  ];
  for (const pattern of patterns) {
    for (const match of text.matchAll(pattern)) {
      matches.add(match[0]);
    }
  }
  return [...matches]
    .map(safeResolve)
    .filter(Boolean)
    .filter(abs => fs.existsSync(abs) && fs.statSync(abs).isFile());
}

function formatFileContent(abs) {
  const rel = path.relative(ROOT, abs);
  const ext = path.extname(abs).toLowerCase();
  const raw = fs.readFileSync(abs, 'utf8');
  const content = raw.length > 120000
    ? `${raw.slice(0, 120000)}\n\n[truncated ${raw.length - 120000} chars]`
    : raw;
  if (ext === '.md' || ext === '.markdown') {
    return `## Inlined file: ${rel}\n\n${content}`;
  }
  const fence = ext === '.html' ? 'html' : ext === '.json' ? 'json' : '';
  return `## Inlined file: ${rel}\n\n\`\`\`${fence}\n${content}\n\`\`\``;
}

export function isRedirectOnlyHermesResponse(response) {
  const text = String(response || '').trim();
  if (!text) return false;
  const hasRedirect = REDIRECT_PATTERNS.some(pattern => pattern.test(text));
  const wordCount = text.split(/\s+/).filter(Boolean).length;
  return hasRedirect && wordCount < 220;
}

export function enforceHermesArtifactFormat(response, { title = 'Hermes output' } = {}) {
  const tagged = extractTaggedArtifact(response);
  if (tagged) {
    return {
      ok: true,
      content: tagged,
      source: 'tagged',
      violations: [],
    };
  }

  const files = extractReferencedFiles(response);
  if (files.length) {
    return {
      ok: true,
      content: [
        `# ${title}`,
        '',
        'Hermes returned file/path references instead of a formatted artifact body. madarX inlined the referenced local file content below.',
        '',
        ...files.map(formatFileContent),
        '',
        '## Raw Hermes response',
        '',
        String(response || '').trim(),
      ].join('\n'),
      source: 'referenced-files',
      violations: ['missing_madarx_artifact_tags'],
    };
  }

  if (isRedirectOnlyHermesResponse(response)) {
    return {
      ok: false,
      content: [
        `# ${title}`,
        '',
        'Hermes returned a redirect-style answer instead of artifact content.',
        '',
        '## Format violation',
        '',
        `Hermes must return the actual artifact body between \`${START_TAG}\` and \`${END_TAG}\`, not only a link, path, or instruction to open another window.`,
        '',
        '## Raw Hermes response',
        '',
        String(response || '').trim(),
      ].join('\n'),
      source: 'violation',
      violations: ['missing_madarx_artifact_tags', 'redirect_only_response'],
    };
  }

  return {
    ok: true,
    content: String(response || '').trim(),
    source: 'raw',
    violations: ['missing_madarx_artifact_tags'],
  };
}
