/**
 * Add collection core logic.
 * Pure function that mutates config - caller handles I/O.
 *
 * @module src/collection/add
 */

import type { Config } from "../config/types";
import type { AddCollectionInput, CollectionResult } from "./types";

import {
  type Collection,
  CollectionSchema,
  DEFAULT_EXCLUDES,
  DEFAULT_PATTERN,
  pathExists,
  toAbsolutePath,
} from "../config";

/**
 * Parse comma-separated string or array into deduplicated array.
 */
function parseList(input: string[] | string | undefined): string[] {
  if (!input) {
    return [];
  }
  if (Array.isArray(input)) {
    return [...new Set(input.map((s) => s.trim()).filter(Boolean))];
  }
  return [
    ...new Set(
      input
        .split(",")
        .map((s) => s.trim())
        .filter(Boolean)
    ),
  ];
}

/**
 * Add a collection to config.
 *
 * @param config - Current config (not mutated)
 * @param input - Collection input
 * @returns New config with collection added, or error
 */
export async function addCollection(
  config: Config,
  input: AddCollectionInput
): Promise<CollectionResult> {
  const collectionName = input.name.toLowerCase();

  // Expand and validate path
  const absolutePath = toAbsolutePath(input.path);

  // Check if path exists
  const exists = await pathExists(absolutePath);
  if (!exists) {
    return {
      ok: false,
      code: "PATH_NOT_FOUND",
      message: `Path does not exist: ${absolutePath}`,
    };
  }

  // Check for duplicate name
  const existing = config.collections.find((c) => c.name === collectionName);
  if (existing) {
    return {
      ok: false,
      code: "DUPLICATE",
      message: `Collection "${collectionName}" already exists`,
    };
  }

  // Check for duplicate path
  const existingPath = config.collections.find((c) => c.path === absolutePath);
  if (existingPath) {
    return {
      ok: false,
      code: "DUPLICATE_PATH",
      message: `Path is already indexed by collection "${existingPath.name}"`,
    };
  }

  // Parse include/exclude lists
  const includeList = parseList(input.include);
  const excludeList =
    parseList(input.exclude).length > 0
      ? parseList(input.exclude)
      : [...DEFAULT_EXCLUDES];

  // Build collection
  const collection: Collection = {
    name: collectionName,
    path: absolutePath,
    pattern: input.pattern ?? DEFAULT_PATTERN,
    include: includeList,
    exclude: excludeList,
    models: input.models,
    updateCmd: input.updateCmd,
  };

  // Validate collection
  const validation = CollectionSchema.safeParse(collection);
  if (!validation.success) {
    return {
      ok: false,
      code: "VALIDATION",
      message: `Invalid collection: ${validation.error.issues[0]?.message ?? "unknown error"}`,
    };
  }

  // Create new config with collection added
  const newConfig: Config = {
    ...config,
    collections: [...config.collections, validation.data],
  };

  return {
    ok: true,
    config: newConfig,
    collection: validation.data,
  };
}
