import {
  extractUcfsForSfc,
  type Framework,
  type UniversalComponentFact,
} from "../ucf/index.js";
import { normalizeScanSourcePath } from "./paths.js";
import type { ScanSource, ScanSourceFile } from "./types.js";

const SFC_EXTENSIONS = [".vue", ".svelte"];

export interface ExtractSfcUcfsFromSourceInput {
  source: ScanSource;
  files: readonly ScanSourceFile[];
  sourceCommit: string;
  adapterVersion?: string;
}

export type SfcUcfSourceDiagnosticCode =
  | "missing_file"
  | "invalid_path"
  | "unsupported_file";

export interface SfcUcfSourceDiagnostic {
  code: SfcUcfSourceDiagnosticCode;
  severity: "info" | "warn";
  message: string;
  filePath?: string;
}

export interface ExtractSfcUcfsFromSourceResult {
  ucfs: UniversalComponentFact[];
  diagnostics: SfcUcfSourceDiagnostic[];
}

export async function extractSfcUcfsFromSource(
  input: ExtractSfcUcfsFromSourceInput
): Promise<UniversalComponentFact[]> {
  return (await extractSfcUcfsFromSourceWithDiagnostics(input)).ucfs;
}

export async function extractSfcUcfsFromSourceWithDiagnostics(
  input: ExtractSfcUcfsFromSourceInput
): Promise<ExtractSfcUcfsFromSourceResult> {
  const sources = [];
  const diagnostics: SfcUcfSourceDiagnostic[] = [];

  for (const file of input.files) {
    const relPath = normalizeScanSourcePath(file.relPath);
    if (!relPath) {
      diagnostics.push({
        code: "invalid_path",
        severity: "warn",
        message: `Invalid source path: ${file.relPath}`,
        filePath: file.relPath,
      });
      continue;
    }
    if (!isSfcSourcePath(relPath)) {
      diagnostics.push({
        code: "unsupported_file",
        severity: "info",
        message: `Unsupported SFC source extension: ${relPath}`,
        filePath: relPath,
      });
      continue;
    }

    const content = await input.source.readFile(relPath);
    if (content === null) {
      diagnostics.push({
        code: "missing_file",
        severity: "warn",
        message: `Unable to read source file: ${relPath}`,
        filePath: relPath,
      });
      continue;
    }
    sources.push({ filePath: relPath, source: content });
  }

  return {
    ucfs: extractUcfsForSfc({
      sources,
      sourceCommit: input.sourceCommit,
      adapterVersion: input.adapterVersion,
    }),
    diagnostics,
  };
}

function isSfcSourcePath(path: string): boolean {
  return SFC_EXTENSIONS.some((ext) => path.endsWith(ext));
}

export type SfcFramework = Extract<Framework, "vue" | "svelte">;
