import "dotenv/config";
import express from "express";
import cors from "cors";
import fs from "node:fs";
import path from "node:path";
import { PluginRegistry } from "./registry.js";
import { runtimeBootstrapScript } from "./bootstrap.js";
const app = express();
app.use(express.json({ limit: "10mb" }));
const port = Number(process.env.PORT || 4110);
const basePath = process.env.RUNTIME_BASE_PATH || "";
const pluginsDir = path.resolve(process.env.PLUGINS_DIR || "./plugins");
const dataDir = path.resolve(process.env.DATA_DIR || "./data");
const stateFile = path.join(dataDir, "plugin-state.json");
const allowOrigin = process.env.ALLOW_ORIGIN || "*";
const owncloudBaseUrl = process.env.OWNCLOUD_BASE_URL || "https://owncloud.example.com";
const owncloudUser = process.env.OWNCLOUD_DEMO_USER || "demo@peowco.com";
app.use(cors({ origin: allowOrigin === "*" ? true : allowOrigin, credentials: true }));
const registry = new PluginRegistry(pluginsDir, stateFile, basePath);
registry.load();
function html(body, title = "Mailcow Plugin Runtime") {
    return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${title}</title><style>
  body{font-family:Inter,Arial,sans-serif;margin:2rem;background:#fafafa;color:#111}
  .card{border:1px solid #ddd;border-radius:12px;padding:1rem;margin-bottom:1rem;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,.04)}
  code,pre{background:#f5f5f5;padding:2px 4px;border-radius:6px} pre{padding:1rem;overflow:auto}
  .row{display:flex;gap:1rem;flex-wrap:wrap}.pill{display:inline-block;padding:.2rem .5rem;border:1px solid #ddd;border-radius:999px;margin:.1rem .2rem .1rem 0}
  button{border:1px solid #333;background:#111;color:#fff;padding:.5rem .75rem;border-radius:8px;cursor:pointer}
  .muted{color:#555}
  .toolbar-anchor,.attachments-anchor{padding:.75rem;border:1px dashed #bbb;border-radius:10px;background:#fcfcfc;margin:.75rem 0}
  </style></head><body>${body}</body></html>`;
}
function pluginUiDir(pluginId) {
    return path.join(pluginsDir, pluginId, "ui");
}
function pluginRootDir(pluginId) {
    return path.join(pluginsDir, pluginId);
}
function sanitizePluginId(pluginId) {
    return /^[a-z0-9][a-z0-9-]*$/i.test(pluginId) ? pluginId : null;
}
app.get(`${basePath}/health`, (_req, res) => res.json({ ok: true, version: "0.2.0", pluginsDir, dataDir, basePath, owncloudBaseUrl }));
app.get(`${basePath}/api/runtime/plugins`, (_req, res) => {
    registry.load();
    res.json({ ok: true, version: "0.2.0", plugins: registry.list() });
});
app.get(`${basePath}/api/runtime/hooks`, (_req, res) => {
    registry.load();
    res.json({ ok: true, version: "0.2.0", hooks: registry.resolvedHooks(), index: registry.hooksIndex() });
});
app.post(`${basePath}/api/runtime/plugins/:id/enable`, (req, res) => {
    registry.load();
    const p = registry.enable(req.params.id);
    if (!p)
        return res.status(404).json({ ok: false, error: "plugin_not_found" });
    res.json({ ok: true, plugin: p });
});
app.post(`${basePath}/api/runtime/plugins/:id/disable`, (req, res) => {
    registry.load();
    const p = registry.disable(req.params.id);
    if (!p)
        return res.status(404).json({ ok: false, error: "plugin_not_found" });
    res.json({ ok: true, plugin: p });
});
app.get(`${basePath}/runtime/bootstrap.js`, (_req, res) => res.type("application/javascript").send(runtimeBootstrapScript(basePath)));
app.use(`${basePath}/plugins/:pluginId/ui`, (req, res, next) => {
    const pluginId = sanitizePluginId(req.params.pluginId);
    if (!pluginId)
        return res.status(400).send("invalid plugin id");
    return express.static(pluginUiDir(pluginId))(req, res, next);
});
app.get(`${basePath}/plugins/:pluginId/manifest`, (req, res) => {
    registry.load();
    const pluginId = sanitizePluginId(req.params.pluginId);
    if (!pluginId)
        return res.status(400).json({ ok: false, error: "invalid_plugin_id" });
    const record = registry.get(pluginId);
    if (!record)
        return res.status(404).json({ ok: false, error: "plugin_not_found" });
    res.json({ ok: true, plugin: record });
});
app.get(`${basePath}/plugins/owncloud-attach/api/me`, (_req, res) => {
    res.json({
        ok: true,
        user: {
            id: owncloudUser,
            email: owncloudUser,
            displayName: process.env.OWNCLOUD_DEMO_DISPLAY_NAME || "Peowco Demo User",
            owncloudBaseUrl,
            authMode: process.env.OWNCLOUD_AUTH_MODE || "oidc-proxy",
        },
    });
});
app.get(`${basePath}/plugins/owncloud-attach/api/files`, (req, res) => {
    const requestedPath = String(req.query.path || "/");
    const mockFilesPath = path.join(pluginRootDir("owncloud-attach"), "data", "files.json");
    const sample = fs.existsSync(mockFilesPath)
        ? JSON.parse(fs.readFileSync(mockFilesPath, "utf8"))
        : { cwd: requestedPath, items: [] };
    res.json({
        ok: true,
        source: process.env.OWNCLOUD_LISTING_MODE || "mock",
        cwd: requestedPath,
        items: sample.items || [],
    });
});
app.post(`${basePath}/plugins/owncloud-attach/api/select`, (req, res) => {
    const body = req.body || {};
    const files = Array.isArray(body.files) ? body.files : [];
    res.json({
        ok: true,
        mode: process.env.OWNCLOUD_ATTACHMENT_MODE || "draft-upload-proxy",
        selectedCount: files.length,
        files: files.map((file) => ({
            id: file.id,
            name: file.name,
            size: file.size,
            status: "queued",
            mailcowDraftUpload: {
                recommendedEndpoint: process.env.MAILCOW_DRAFT_UPLOAD_ENDPOINT || "/api/v1/mail/attachments/upload",
                method: "POST",
            },
        })),
    });
});
app.get(`${basePath}/runtime/ui`, (_req, res) => {
    registry.load();
    const plugins = registry.list();
    const hooks = registry.resolvedHooks();
    res.type("html").send(html(`
      <h1>Mailcow Plugin Runtime v0.2.0</h1>
      <p class="muted">Combined foundation: v0.1.0 registry/runtime + v0.2.0 rendered hook contributions, plugin asset serving, persisted plugin state, and ownCloud reference plugin UI/API.</p>
      <div class="row">
        <div class="card"><strong>Base path</strong><div><code>${basePath || "/"}</code></div></div>
        <div class="card"><strong>Plugins dir</strong><div><code>${pluginsDir}</code></div></div>
        <div class="card"><strong>State file</strong><div><code>${stateFile}</code></div></div>
      </div>
      <h2>Plugins</h2>
      ${plugins
        .map((p) => `<div class="card"><h3>${p.manifest.name}</h3>
            <div><strong>ID:</strong> <code>${p.manifest.id}</code></div>
            <div><strong>Version:</strong> ${p.manifest.version}</div>
            <div><strong>Enabled:</strong> ${p.enabled}</div>
            <div><strong>Valid:</strong> ${p.valid}</div>
            <div><strong>Hooks:</strong> ${(Object.keys(p.manifest.contributions || {}).join(", ") || (p.manifest.hooks || []).join(", ") || "none")}</div>
          </div>`)
        .join("")}
      <h2>Runtime demo</h2>
      <div class="toolbar-anchor" data-mailcow-plugin-hook="mail.compose.toolbar"><strong>Compose toolbar hook target</strong></div>
      <div class="attachments-anchor" data-mailcow-plugin-hook="mail.compose.attachments"><strong>Compose attachments hook target</strong></div>
      <script src="${basePath}/runtime/bootstrap.js"></script>
      <h2>Resolved hooks</h2>
      <pre>${JSON.stringify(hooks, null, 2)}</pre>
    `));
});
app.get(`${basePath}/mailcow/nginx.conf`, (_req, res) => {
    res.type("text/plain").send(`location ${basePath || "/plugins-runtime/"} {
  proxy_pass http://mailcow-plugin-runtime:${port}${basePath || "/plugins-runtime/"};
  proxy_http_version 1.1;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Real-IP $remote_addr;
}`);
});
app.listen(port, () => console.log(`mailcow-plugin-runtime v0.2.0 listening on ${port}`));
