const fs = require("fs");
const path = require("path");
const { db } = require("./db");
const { getPlugins } = require("./plugins");

function readJsonSafe(filePath) {
  try {
    const raw = fs.readFileSync(filePath, "utf8");
    return JSON.parse(raw);
  } catch {
    return null;
  }
}

function loadStatProviders() {
  const providers = [];
  const plugins = getPlugins().filter((plugin) => plugin.enabled);
  for (const plugin of plugins) {
    const manifestPath = path.join(plugin.path, "stats.json");
    if (!fs.existsSync(manifestPath)) {
      continue;
    }
    const manifest = readJsonSafe(manifestPath);
    if (!manifest) {
      continue;
    }
    const providerPath = path.join(
      plugin.path,
      manifest.provider || "stats.js"
    );
    if (!fs.existsSync(providerPath)) {
      continue;
    }
    let provider = null;
    try {
      provider = require(providerPath);
    } catch (error) {
      console.error("Failed to load plugin stats provider", error);
      continue;
    }
    providers.push({ plugin, manifest, provider });
  }
  return providers;
}

function buildProfileSection({ plugin, manifest, provider, userId }) {
  if (!manifest.profile || typeof provider.getProfileStats !== "function") {
    return null;
  }
  let result = null;
  try {
    result = provider.getProfileStats({ db, userId, plugin, manifest });
  } catch (error) {
    console.error("Failed to load plugin profile stats", error);
    return null;
  }
  const stats = Array.isArray(result?.stats) ? result.stats : [];
  return {
    id: manifest.pluginId || plugin.id,
    title: manifest.profile.title || manifest.pluginName || plugin.name,
    emptyMessage:
      manifest.profile.emptyMessage || "No stats available yet.",
    stats
  };
}

function buildLeaderboardSection({ plugin, manifest, provider, limit }) {
  if (!manifest.leaderboards || typeof provider.getLeaderboards !== "function") {
    return null;
  }
  let result = null;
  try {
    result = provider.getLeaderboards({ db, limit, plugin, manifest });
  } catch (error) {
    console.error("Failed to load plugin leaderboards", error);
    return null;
  }
  const boards = Array.isArray(result?.boards) ? result.boards : [];
  return {
    id: manifest.pluginId || plugin.id,
    title:
      manifest.leaderboards.title || manifest.pluginName || plugin.name,
    emptyMessage:
      manifest.leaderboards.emptyMessage || "No data available yet.",
    boards
  };
}

function getPluginProfileStats(userId) {
  if (!userId) {
    return [];
  }
  return loadStatProviders()
    .map((entry) => buildProfileSection({ ...entry, userId }))
    .filter(Boolean);
}

async function getAdminDashboardSections() {
  const sections = await Promise.all(loadStatProviders().map(async ({ plugin, manifest, provider }) => {
    if (!manifest.adminDashboard || typeof provider.getAdminDashboardStats !== "function") return null;
    try {
      const result = await provider.getAdminDashboardStats({ db, plugin, manifest });
      if (!result || typeof result !== "object") return null;
      return {
        id: String(result.id || manifest.pluginId || plugin.id).slice(0, 120),
        eyebrow: String(result.eyebrow || "Companion service").slice(0, 80),
        title: String(result.title || manifest.adminDashboard.title || plugin.name).slice(0, 160),
        description: String(result.description || manifest.adminDashboard.description || "").slice(0, 500),
        status: normalizeDashboardStatus(result.status),
        metrics: normalizeDashboardMetrics(result.metrics),
        issues: Array.isArray(result.issues) ? result.issues.map((issue) => String(issue).slice(0, 240)).slice(0, 6) : [],
        actions: normalizeDashboardActions(result.actions)
      };
    } catch (error) {
      console.error(`Failed to load ${plugin.id} admin dashboard stats`, error);
      return {
        id: plugin.id,
        eyebrow: "Companion service",
        title: manifest.adminDashboard.title || plugin.name,
        description: "This plugin's dashboard summary could not be loaded. Its normal settings remain available.",
        status: { label: "Summary unavailable", tone: "danger" },
        metrics: [], issues: ["Open the plugin page or diagnostics for details."],
        actions: normalizeDashboardActions([{ label: "Open settings", href: `/plugins/${encodeURIComponent(plugin.id)}`, method: "get" }])
      };
    }
  }));
  return sections.filter(Boolean);
}

function normalizeDashboardStatus(value) {
  const tone = ["success", "warning", "danger", "info", "muted"].includes(value?.tone) ? value.tone : "muted";
  return { label: String(value?.label || "Status unavailable").slice(0, 120), tone };
}

function normalizeDashboardMetrics(values) {
  if (!Array.isArray(values)) return [];
  return values.map((entry) => ({ label: String(entry?.label || "Status").slice(0, 80), value: String(entry?.value ?? "—").slice(0, 120) })).slice(0, 6);
}

function normalizeDashboardActions(values) {
  if (!Array.isArray(values)) return [];
  return values.filter((entry) => /^\/(?!\/)/.test(String(entry?.href || ""))).map((entry) => ({
    label: String(entry.label || "Open").slice(0, 80), href: String(entry.href).slice(0, 300),
    method: entry.method === "post" ? "post" : "get", primary: entry.primary === true,
    disabled: entry.disabled === true, disabledReason: String(entry.disabledReason || "").slice(0, 200)
  })).slice(0, 4);
}

function getPluginLeaderboards(limit = 10) {
  return loadStatProviders()
    .map((entry) => buildLeaderboardSection({ ...entry, limit }))
    .filter(Boolean);
}

module.exports = {
  getPluginProfileStats,
  getPluginLeaderboards,
  getAdminDashboardSections
};
