import { CloseBotClient, err } from "../client.js";
import type { ToolDefinition, ToolResult, LeaderboardResponse } from "../types.js";

export const tools: ToolDefinition[] = [
  {
    name: "leaderboard_app",
    description:
      "Rich leaderboard visualization showing global and local rankings by metric (responses, bookings, contacts). Returns HTML.",
    inputSchema: {
      type: "object",
      properties: {
        metric: {
          type: "string",
          enum: ["responses", "bookings", "contacts"],
          description: "Metric to rank by (default: responses)",
        },
        scope: {
          type: "string",
          enum: ["global", "local"],
          description: "Global or local leaderboard (default: global)",
        },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        numTopLeaders: {
          type: "integer",
          description: "Number of top leaders to show (global, default 10)",
        },
        numSurrounding: {
          type: "integer",
          description: "Number of surrounding agencies (local, default 5)",
        },
      },
    },
  },
];

function escapeHtml(s: string): string {
  return s
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}

function medalEmoji(rank: number): string {
  if (rank === 1) return "🥇";
  if (rank === 2) return "🥈";
  if (rank === 3) return "🥉";
  return `#${rank}`;
}

function renderLeaderboard(
  entries: LeaderboardResponse[],
  metric: string,
  scope: string,
  start?: string,
  end?: string
): string {
  const metricLabel = metric.charAt(0).toUpperCase() + metric.slice(1);
  const scopeLabel = scope === "local" ? "Local" : "Global";
  const dateRange =
    start && end
      ? `${new Date(start).toLocaleDateString()} – ${new Date(end).toLocaleDateString()}`
      : "All time";

  const rows = entries
    .map((e, i) => {
      const rank = e.rank ?? i + 1;
      const medal = medalEmoji(rank);
      const name = escapeHtml(e.agencyName || e.agencyId || "Unknown");
      const value = e.value ?? 0;
      const isYou = e.isCurrentAgency ? ' style="background:#2d3748;font-weight:bold"' : "";
      const youBadge = e.isCurrentAgency
        ? ' <span style="background:#4299e1;color:#fff;padding:1px 6px;border-radius:8px;font-size:11px">YOU</span>'
        : "";
      return `<tr${isYou}><td style="text-align:center;font-size:18px">${medal}</td><td>${name}${youBadge}</td><td style="text-align:right;font-variant-numeric:tabular-nums">${value.toLocaleString()}</td></tr>`;
    })
    .join("\n");

  return `<div style="font-family:system-ui,-apple-system,sans-serif;background:#1a202c;color:#e2e8f0;padding:20px;border-radius:12px;max-width:600px">
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px">
    <div>
      <h2 style="margin:0;font-size:20px;color:#fff">${scopeLabel} Leaderboard</h2>
      <span style="color:#a0aec0;font-size:13px">${metricLabel} · ${dateRange}</span>
    </div>
    <div style="display:flex;gap:6px">
      <span style="background:${metric === "responses" ? "#4299e1" : "#2d3748"};color:#fff;padding:4px 10px;border-radius:6px;font-size:12px;cursor:pointer">Responses</span>
      <span style="background:${metric === "bookings" ? "#48bb78" : "#2d3748"};color:#fff;padding:4px 10px;border-radius:6px;font-size:12px;cursor:pointer">Bookings</span>
      <span style="background:${metric === "contacts" ? "#ed8936" : "#2d3748"};color:#fff;padding:4px 10px;border-radius:6px;font-size:12px;cursor:pointer">Contacts</span>
    </div>
  </div>
  <table style="width:100%;border-collapse:collapse">
    <thead>
      <tr style="border-bottom:1px solid #4a5568">
        <th style="text-align:center;padding:8px 4px;color:#a0aec0;font-size:12px;width:50px">Rank</th>
        <th style="text-align:left;padding:8px;color:#a0aec0;font-size:12px">Agency</th>
        <th style="text-align:right;padding:8px;color:#a0aec0;font-size:12px">${metricLabel}</th>
      </tr>
    </thead>
    <tbody>
      ${rows || '<tr><td colspan="3" style="text-align:center;padding:20px;color:#718096">No leaderboard data available</td></tr>'}
    </tbody>
  </table>
  <div style="margin-top:12px;text-align:center;color:#718096;font-size:11px">${entries.length} agencies shown</div>
</div>`;
}

export async function handle(
  client: CloseBotClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    const metric = (args.metric as string) || "responses";
    const scope = (args.scope as string) || "global";
    const start = args.start as string | undefined;
    const end = args.end as string | undefined;

    let entries: LeaderboardResponse[];

    if (scope === "local") {
      entries = await client.get<LeaderboardResponse[]>(
        "/botMetric/localleaderboard",
        {
          metric,
          start,
          end,
          numSurroundingAgencies: args.numSurrounding ?? 5,
        }
      );
    } else {
      entries = await client.get<LeaderboardResponse[]>(
        "/botMetric/leaderboard",
        {
          metric,
          start,
          end,
          numTopLeaders: args.numTopLeaders ?? 10,
        }
      );
    }

    const html = renderLeaderboard(
      Array.isArray(entries) ? entries : [],
      metric,
      scope,
      start,
      end
    );

    return {
      content: [{ type: "text" as const, text: html }],
    };
  } catch (error) {
    return err(error);
  }
}
