import { EpubBuilder as g } from "@mark-magic/epub";
import { fromMarkdown as v, selectAll as f, toString as b, hastToHtml as k, mdToHast as y } from "@liuli-util/markdown-util";
import { v4 as C } from "uuid";
import { treeMap as M } from "@liuli-util/tree";
import { readFile as L, writeFile as E } from "node:fs/promises";
import { mkdirp as _ } from "fs-extra/esm";
import c from "pathe";
import { keyBy as j } from "lodash-es";
import x from "node:path";
const B = (a) => a.startsWith(":/resource/"), I = (a) => a.startsWith(":/content/"), p = (a) => a.slice(11), m = (a) => ["readme.md", "index.md"].includes(c.basename(a).toLocaleLowerCase());
function u(a) {
  return a.sort((n, h) => {
    const r = n.path, s = h.path;
    if (r === "cover")
      return -1;
    if (s === "cover")
      return 1;
    const t = c.dirname(r), o = c.dirname(s);
    if (t === o) {
      if (m(r))
        return -1;
      if (m(s))
        return 1;
    }
    return r.localeCompare(s);
  });
}
function P(a) {
  const n = {};
  for (const t of a) {
    const o = t.path.split("/");
    let i = n;
    for (let d = 0; d < o.length; d++) {
      const e = o[d];
      i[e] || (i[e] = {}), i = i[e];
    }
    i._self = t;
  }
  function h(t, o = "") {
    const i = [];
    for (const d in t)
      if (d !== "_self") {
        const e = t[d], l = x.join(o, d);
        e._self && i.push(e._self);
        const w = h(e, l);
        w.length > 0 && i.push({ path: l, children: w });
      }
    return i;
  }
  const s = h(n).filter((t) => !m(t.path));
  return M(
    u(s),
    (t) => {
      if (!t.children)
        return t;
      const o = t.children.find(
        (i) => ["readme.md", "index.md"].includes(c.basename(i.path).toLocaleLowerCase())
      );
      if (t.children = u(t.children), !o)
        throw new Error(t.path + " 下必须存在 readme.md 或者 index.md");
      return Object.assign(t, o), t.children = t.children.filter((i) => !m(i.path)), t;
    },
    {
      id: "path",
      children: "children"
    }
  );
}
function N(a) {
  const n = {
    metadata: a.metadata,
    media: [],
    text: [],
    toc: []
  }, h = [];
  return {
    name: "epub",
    async start() {
      if (!a.metadata.cover)
        return;
      const r = C() + c.extname(a.metadata.cover);
      n.media.push({
        id: r,
        buffer: await L(a.metadata.cover)
      }), n.metadata.cover = r, n.text.push({
        id: "cover",
        title: "cover",
        path: "cover",
        content: `<svg
          xmlns="http://www.w3.org/2000/svg"
          height="100%"
          preserveAspectRatio="xMidYMid meet"
          version="1.1"
          viewBox="0 0 1352 2000"
          width="100%"
          xmlns:xlink="http://www.w3.org/1999/xlink"
        >
          <image width="1352" height="2000" xlink:href="../Media/${r}" />
        </svg>`
      });
    },
    async handle(r) {
      const s = v(r.content), t = j(r.resources, (e) => e.id);
      f("image", s).filter((e) => B(e.url)).forEach((e) => {
        const l = p(e.url);
        e.url = "../Media/" + p(e.url) + c.extname(t[l].name);
      }), f("link", s).filter((e) => I(e.url)).forEach((e) => {
        e.url = "./" + p(e.url) + ".xhtml";
      });
      const o = f("heading", s).find((e) => e.depth === 1);
      o != null && o.children[0] && (r.name = b(o.children[0]));
      const i = {
        id: r.id,
        title: r.name,
        path: c.join(...r.path),
        chapterId: r.id
      };
      h.push(i);
      const d = {
        id: r.id,
        title: r.name,
        content: k(y(s), {
          closeSelfClosing: !0
        }),
        path: c.join(...r.path)
      };
      n.text.push(d), r.resources.forEach((e) => {
        n.media.push({
          id: e.id + x.extname(e.name),
          buffer: e.raw
        });
      });
    },
    async end() {
      n.toc = P(h), n.text = u(n.text);
      const r = new g().gen(n);
      await _(c.dirname(a.path)), await E(c.resolve(a.path), await r.generateAsync({ type: "nodebuffer" }));
    }
  };
}
export {
  N as output
};
