import type { ProjectExportOptions, RegexProjectV1 } from "./project.types";
import {
  assertSerializedProjectDocumentWithinLimit,
  MAXIMUM_PROJECT_DOCUMENT_BYTES,
  projectDocumentUtf8ByteLength,
} from "./project-limits";
import { parseRegexProject } from "./project.validation";

export function serializeProject(
  project: RegexProjectV1,
  options: ProjectExportOptions,
): string {
  const document: RegexProjectV1 = {
    ...project,
    updatedAt: new Date().toISOString(),
    testText: options.includeTestText
      ? {
          included: true,
          value: project.testText?.value ?? "",
        }
      : { included: false },
    tests: options.includeUnitTestSubjects
      ? project.tests
      : project.tests.map((test) => ({ ...test, subject: "" })),
  };
  projectDocumentUtf8ByteLength(document, MAXIMUM_PROJECT_DOCUMENT_BYTES - 1);
  const serialized = `${JSON.stringify(document, null, 2)}\n`;
  assertSerializedProjectDocumentWithinLimit(serialized);
  return serialized;
}

export function importProjectDocument(serialized: string): RegexProjectV1 {
  assertSerializedProjectDocumentWithinLimit(serialized);
  let value: unknown;
  try {
    value = JSON.parse(serialized);
  } catch (error) {
    throw new Error("Project document is not valid JSON.", { cause: error });
  }
  return parseRegexProject(value);
}

export function projectFileName(project: RegexProjectV1): string {
  const safe = project.name
    .normalize("NFKD")
    .replace(/[^\p{Letter}\p{Number}._-]+/gu, "-")
    .replace(/^-+|-+$/gu, "")
    .slice(0, 80);
  return `${safe || "regex-project"}.regex-tools.json`;
}
