import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { parse } from "yaml";
import { envString } from "../env.js";

export type N8nWorkflowDefinition = {
  id: string;
  label: string;
  description: string;
  url: string;
  required_roles: string[];
  tags: string[];
};

export type PublicN8nWorkflowDefinition = N8nWorkflowDefinition;

type N8nFile = { n8n_workflows?: N8nWorkflowDefinition[] };

const expandEnv = (value: string): string =>
  value.replace(/\$\{([A-Z0-9_]+)(?::\?[^}]+)?\}/g, (_match, name: string) => process.env[name] ?? "");

const defaultPath = (): string =>
  envString(process.env.N8N_CONFIG_PATH, resolve(process.cwd(), "../../config/n8n-workflows.yml"));

export const loadN8nWorkflows = (
  configPath: string = defaultPath(),
): N8nWorkflowDefinition[] => {
  let raw: string;
  try {
    raw = readFileSync(configPath, "utf8");
  } catch (error) {
    const code = (error as NodeJS.ErrnoException).code;
    if (code === "ENOENT") return [];
    throw error;
  }
  const parsed = parse(raw) as N8nFile | null;
  if (!parsed || !Array.isArray(parsed.n8n_workflows)) return [];
  return parsed.n8n_workflows
    .filter((wf) => wf && typeof wf === "object" && typeof wf.id === "string")
    .map((wf) => ({
      id: String(wf.id).trim(),
      label: String(wf.label ?? wf.id).trim(),
      description: String(wf.description ?? "").trim(),
      url: expandEnv(String(wf.url ?? "").trim()),
      required_roles: Array.isArray(wf.required_roles)
        ? wf.required_roles.map(String)
        : [],
      tags: Array.isArray(wf.tags) ? wf.tags.map(String) : [],
    }))
    .filter((wf) => wf.id.length > 0);
};

export const canUseN8nWorkflow = (userRoles: string[], wf: N8nWorkflowDefinition): boolean => {
  if (!Array.isArray(wf.required_roles) || wf.required_roles.length === 0) return true;
  return wf.required_roles.every((role) => userRoles.includes(role));
};

export const toPublicN8nWorkflow = (wf: N8nWorkflowDefinition): PublicN8nWorkflowDefinition => ({ ...wf });
