/**
 * COL Scanner — Cross-Plugin/User-vs-Plugin Skill Collision (v5 N6)
 *
 * Detects skill-name collisions across plugins and between user-level skills
 * (~/.claude/skills/) and plugin-bundled skills. Skill names come from the
 * directory layout (basename of dirname(SKILL.md)) — that matches how
 * enumerateSkills resolves them.
 *
 * Detection rules (from Step 22a research, confidence: medium):
 *   - Two or more plugins exposing a skill with the same directory name:
 *     severity `low` (CA-COL-001) — order ambiguity even when invocation is
 *     namespaced via `/plugin:skill`.
 *   - A user-level skill and a plugin skill with the same name: severity
 *     `medium` (CA-COL-001) — bare invocation may resolve unpredictably.
 *   - Plugin-vs-built-in collisions: out of scope for v5.0.0 (insufficient
 *     verification — see docs/v5-namespace-research.md).
 *
 * Each finding's `details.namespaces` array carries `{ source, name }` for
 * every conflicting source so downstream tooling can render a per-collision
 * report.
 *
 * Zero external dependencies.
 */

import { finding, scannerResult } from './lib/output.mjs';
import { SEVERITY } from './lib/severity.mjs';
import { enumeratePlugins, enumerateSkills } from './lib/active-config-reader.mjs';

const SCANNER = 'COL';

/**
 * Group skills by name. Returns Map<name, Array<skill>>.
 */
function groupSkillsByName(skills) {
  const grouped = new Map();
  for (const s of skills) {
    if (!s || typeof s.name !== 'string') continue;
    if (!grouped.has(s.name)) grouped.set(s.name, []);
    grouped.get(s.name).push(s);
  }
  return grouped;
}

/**
 * Main scanner entry point.
 *
 * @param {string} targetPath unused (collision check is HOME-scoped)
 * @param {object} discovery unused (collision check ignores project discovery)
 */
export async function scan(_targetPath, _discovery) {
  const start = Date.now();
  const findings = [];

  const plugins = await enumeratePlugins();
  const allSkills = await enumerateSkills(plugins);

  const grouped = groupSkillsByName(allSkills);

  for (const [name, skills] of grouped) {
    if (skills.length < 2) continue;

    const userSkill = skills.find(s => s.source === 'user');
    const pluginSkills = skills.filter(s => s.source === 'plugin');

    if (userSkill && pluginSkills.length > 0) {
      // User-vs-plugin collision (severity medium per Step 22a)
      const namespaces = [
        { source: 'user', name, path: userSkill.path },
        ...pluginSkills.map(s => ({
          source: `plugin:${s.pluginName}`,
          name,
          path: s.path,
        })),
      ];
      findings.push(finding({
        scanner: SCANNER,
        severity: SEVERITY.medium,
        title: `Skill name "${name}" collides between user-level and plugin sources`,
        description:
          `A user-level skill at ${userSkill.path} shares its directory name "${name}" ` +
          `with ${pluginSkills.length} plugin-bundled skill` +
          `${pluginSkills.length === 1 ? '' : 's'}. Bare invocation may resolve ` +
          'unpredictably; the user has to remember which definition is currently active.',
        file: userSkill.path,
        evidence:
          `name="${name}"; sources=` +
          [`user`, ...pluginSkills.map(s => `plugin:${s.pluginName}`)].join(','),
        recommendation:
          `Rename either the user skill (~/.claude/skills/${name}/) or one of the plugin ` +
          'skills, or rely on namespaced invocation paths and remove the bare alias to ' +
          'eliminate the ambiguity.',
        category: 'plugin-hygiene',
        details: { namespaces },
      }));
    } else if (pluginSkills.length >= 2) {
      // Plugin-vs-plugin collision (severity low per Step 22a)
      const pluginNames = pluginSkills.map(s => s.pluginName);
      findings.push(finding({
        scanner: SCANNER,
        severity: SEVERITY.low,
        title: `Skill name "${name}" used by multiple plugins`,
        description:
          `${pluginSkills.length} plugins (${pluginNames.join(', ')}) expose a skill ` +
          `named "${name}". Even when invocation is namespaced via /plugin:skill, ` +
          'shared names create ambiguity in error messages, search results, and the ' +
          'plugin-skills enumeration.',
        file: pluginSkills[0].path,
        evidence: `name="${name}"; plugins=${pluginNames.join(',')}`,
        recommendation:
          'Coordinate naming across plugins, or rename one to clarify intent. The ' +
          'shared name forces every reader to disambiguate by source.',
        category: 'plugin-hygiene',
        details: {
          namespaces: pluginSkills.map(s => ({
            source: `plugin:${s.pluginName}`,
            name,
            path: s.path,
          })),
        },
      }));
    }
  }

  return scannerResult(SCANNER, 'ok', findings, allSkills.length, Date.now() - start);
}
