import { pickedCompletion, type Completion } from "@codemirror/autocomplete";

export interface MarkdownCodeLanguage {
  label: string;
  name: string;
  aliases: string[];
  shiki: string;
}

export const markdownCodeLanguages: MarkdownCodeLanguage[] = [
  { label: "text", name: "Plain text", aliases: ["txt", "plaintext"], shiki: "text" },
  { label: "javascript", name: "JavaScript", aliases: ["js", "node"], shiki: "javascript" },
  { label: "typescript", name: "TypeScript", aliases: ["ts"], shiki: "typescript" },
  { label: "jsx", name: "JSX", aliases: [], shiki: "jsx" },
  { label: "tsx", name: "TSX", aliases: [], shiki: "tsx" },
  { label: "vue", name: "Vue", aliases: ["vuejs"], shiki: "vue" },
  { label: "html", name: "HTML", aliases: ["htm"], shiki: "html" },
  { label: "css", name: "CSS", aliases: [], shiki: "css" },
  { label: "scss", name: "SCSS", aliases: ["sass"], shiki: "scss" },
  { label: "json", name: "JSON", aliases: ["jsonc"], shiki: "json" },
  { label: "yaml", name: "YAML", aliases: ["yml"], shiki: "yaml" },
  { label: "markdown", name: "Markdown", aliases: ["md"], shiki: "markdown" },
  { label: "python", name: "Python", aliases: ["py"], shiki: "python" },
  { label: "java", name: "Java", aliases: [], shiki: "java" },
  { label: "kotlin", name: "Kotlin", aliases: ["kt"], shiki: "kotlin" },
  { label: "c", name: "C", aliases: [], shiki: "c" },
  { label: "cpp", name: "C++", aliases: ["c++"], shiki: "cpp" },
  { label: "csharp", name: "C#", aliases: ["cs", "c#"], shiki: "csharp" },
  { label: "go", name: "Go", aliases: ["golang"], shiki: "go" },
  { label: "rust", name: "Rust", aliases: ["rs"], shiki: "rust" },
  { label: "php", name: "PHP", aliases: [], shiki: "php" },
  { label: "ruby", name: "Ruby", aliases: ["rb"], shiki: "ruby" },
  { label: "swift", name: "Swift", aliases: [], shiki: "swift" },
  { label: "sql", name: "SQL", aliases: [], shiki: "sql" },
  { label: "bash", name: "Bash", aliases: ["sh", "shell", "zsh"], shiki: "bash" },
  { label: "powershell", name: "PowerShell", aliases: ["ps1", "pwsh"], shiki: "powershell" },
  { label: "dockerfile", name: "Dockerfile", aliases: ["docker"], shiki: "dockerfile" },
  { label: "xml", name: "XML", aliases: [], shiki: "xml" },
  { label: "toml", name: "TOML", aliases: [], shiki: "toml" },
];

const languageLookup = new Map<string, MarkdownCodeLanguage>();

for (const language of markdownCodeLanguages) {
  languageLookup.set(language.label, language);
  for (const alias of language.aliases) {
    languageLookup.set(alias, language);
  }
}

export function resolveMarkdownCodeLanguage(value: string | null | undefined) {
  const normalized = value?.trim().toLowerCase().split(/\s+/, 1)[0] || "";
  return languageLookup.get(normalized) ?? null;
}

const RECENT_LANGUAGES_KEY = "markdown-recent-code-languages";

function readRecentLanguages() {
  try {
    const stored = localStorage.getItem(RECENT_LANGUAGES_KEY);
    const value = stored ? JSON.parse(stored) : [];
    return Array.isArray(value)
      ? value.filter((item): item is string => typeof item === "string").slice(0, 5)
      : [];
  } catch {
    return [];
  }
}

export function rememberMarkdownCodeLanguage(label: string) {
  const next = [label, ...readRecentLanguages().filter((item) => item !== label)].slice(0, 5);
  try {
    localStorage.setItem(RECENT_LANGUAGES_KEY, JSON.stringify(next));
  } catch {
    // Completion remains available when storage is disabled.
  }
}

export function getMarkdownLanguageCompletions(): Completion[] {
  const recent = readRecentLanguages();

  return markdownCodeLanguages.map((language, index) => ({
    label: language.label,
    displayLabel: language.name,
    detail: language.aliases.length > 0 ? language.aliases.join(", ") : language.label,
    type: "keyword",
    boost: recent.includes(language.label) ? 100 - recent.indexOf(language.label) : -index,
    apply(view, completion, from, to) {
      rememberMarkdownCodeLanguage(language.label);
      view.dispatch({
        changes: { from, to, insert: language.label },
        annotations: pickedCompletion.of(completion),
      });
    },
  }));
}
