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

export const tools: ToolDefinition[] = [
  {
    name: "library_manager_app",
    description: "Knowledge base library viewer showing files with type icons, source attachments, scrape status, and size. Returns HTML visualization.",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "Optional: show detail for a specific file including scrape pages" },
      },
    },
  },
];

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

function fileIcon(fileType: string | null | undefined): string {
  const t = (fileType || "").toLowerCase();
  if (t.includes("pdf")) return "📄";
  if (t.includes("doc") || t.includes("word")) return "📝";
  if (t.includes("csv") || t.includes("excel") || t.includes("spreadsheet")) return "📊";
  if (t.includes("image") || t.includes("png") || t.includes("jpg")) return "🖼️";
  if (t.includes("webscrape") || t.includes("web") || t.includes("html")) return "🌐";
  if (t.includes("text") || t.includes("txt")) return "📃";
  if (t.includes("json")) return "🔧";
  return "📁";
}

function formatSize(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

function statusBadge(status: string | null | undefined): string {
  const s = (status || "").toLowerCase();
  if (s === "ready" || s === "completed" || s === "processed")
    return '<span style="background:#1a3a2a;color:#4ecdc4;padding:2px 8px;border-radius:4px;font-size:10px;">✅ Ready</span>';
  if (s === "processing" || s === "pending")
    return '<span style="background:#3a3a1a;color:#ffd93d;padding:2px 8px;border-radius:4px;font-size:10px;">⏳ Processing</span>';
  if (s === "error" || s === "failed")
    return '<span style="background:#3a1a1a;color:#ff6b6b;padding:2px 8px;border-radius:4px;font-size:10px;">❌ Error</span>';
  return `<span style="background:#1a1a2e;color:#888;padding:2px 8px;border-radius:4px;font-size:10px;">${escapeHtml(status || "Unknown")}</span>`;
}

function renderFileList(files: FileDto[]): string {
  const totalSize = files.reduce((sum, f) => sum + (f.fileSize || 0), 0);

  const rows = files
    .map((f) => {
      const icon = fileIcon(f.fileType);
      const sources = (f.sources || [])
        .map(
          (s) =>
            `<span style="background:#1a2a3e;padding:1px 6px;border-radius:4px;font-size:10px;color:#7ec8e3;">${escapeHtml(s.name || s.id || "")}</span>`
        )
        .join(" ");
      const modified = f.lastModified
        ? new Date(f.lastModified).toLocaleDateString()
        : "—";

      return `
        <div style="background:#1a1a2e;border-radius:10px;padding:14px;display:flex;align-items:center;gap:14px;">
          <div style="font-size:28px;width:36px;text-align:center;">${icon}</div>
          <div style="flex:1;min-width:0;">
            <div style="font-weight:600;font-size:13px;color:#e0e0e0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
              ${escapeHtml(f.fileName || "Unnamed")}
            </div>
            <div style="display:flex;gap:8px;align-items:center;margin-top:4px;">
              ${statusBadge(f.fileStatus)}
              <span style="font-size:11px;color:#666;">${escapeHtml(f.fileType || "")}</span>
              <span style="font-size:11px;color:#666;">${formatSize(f.fileSize || 0)}</span>
              <span style="font-size:11px;color:#666;">${escapeHtml(modified)}</span>
            </div>
            ${sources ? `<div style="margin-top:6px;display:flex;gap:4px;flex-wrap:wrap;">${sources}</div>` : ""}
          </div>
          <div style="font-size:10px;color:#444;font-family:monospace;white-space:nowrap;">${escapeHtml(f.fileId || "")}</div>
        </div>`;
    })
    .join("");

  return `
    <div style="font-family:-apple-system,BlinkMacSystemFont,sans-serif;background:#0d0d1a;color:#e0e0e0;padding:20px;border-radius:16px;">
      <h2 style="margin:0 0 4px;color:#fff;">📚 Library Manager</h2>
      <div style="font-size:12px;color:#666;margin-bottom:16px;">
        ${files.length} files · ${formatSize(totalSize)} total
      </div>
      <div style="display:flex;flex-direction:column;gap:8px;">
        ${rows || '<div style="padding:40px;text-align:center;color:#666;">No files. Use upload_file or create_web_scrape to add content.</div>'}
      </div>
      <div style="margin-top:12px;font-size:11px;color:#555;">
        💡 Use <code>upload_file</code> to upload, <code>create_web_scrape</code> to scrape websites, <code>attach_file_to_source</code> to connect to sources
      </div>
    </div>`;
}

function renderFileDetail(file: FileDto, scrapePages: Array<{ url?: string; enabled?: boolean }>): string {
  const sources = (file.sources || [])
    .map(
      (s) =>
        `<div style="background:#1a2a3e;padding:8px 12px;border-radius:6px;display:flex;justify-content:space-between;">
          <span style="font-size:12px;color:#7ec8e3;">${escapeHtml(s.name || "Unnamed")}</span>
          <span style="font-size:10px;color:#666;">${escapeHtml(s.category || "")} · ${escapeHtml(s.id || "")}</span>
        </div>`
    )
    .join("");

  const pages = scrapePages
    .map(
      (p) =>
        `<div style="display:flex;align-items:center;gap:8px;padding:4px 0;">
          <span style="font-size:14px;">${p.enabled ? "✅" : "❌"}</span>
          <span style="font-size:12px;color:#aaa;word-break:break-all;">${escapeHtml(p.url || "")}</span>
        </div>`
    )
    .join("");

  return `
    <div style="font-family:-apple-system,BlinkMacSystemFont,sans-serif;background:#0d0d1a;color:#e0e0e0;padding:20px;border-radius:16px;">
      <div style="display:flex;align-items:center;gap:12px;margin-bottom:16px;">
        <span style="font-size:36px;">${fileIcon(file.fileType)}</span>
        <div>
          <h2 style="margin:0;color:#fff;">${escapeHtml(file.fileName || "Unnamed")}</h2>
          <div style="font-size:11px;color:#555;font-family:monospace;">${escapeHtml(file.fileId || "")}</div>
        </div>
      </div>

      <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:20px;">
        <div style="background:#1a1a2e;padding:12px;border-radius:8px;text-align:center;">
          <div style="font-size:11px;color:#888;">Status</div>
          <div style="margin-top:4px;">${statusBadge(file.fileStatus)}</div>
        </div>
        <div style="background:#1a1a2e;padding:12px;border-radius:8px;text-align:center;">
          <div style="font-size:11px;color:#888;">Type</div>
          <div style="font-size:13px;margin-top:4px;">${escapeHtml(file.fileType || "—")}</div>
        </div>
        <div style="background:#1a1a2e;padding:12px;border-radius:8px;text-align:center;">
          <div style="font-size:11px;color:#888;">Size</div>
          <div style="font-size:13px;margin-top:4px;">${formatSize(file.fileSize || 0)}</div>
        </div>
        <div style="background:#1a1a2e;padding:12px;border-radius:8px;text-align:center;">
          <div style="font-size:11px;color:#888;">Modified</div>
          <div style="font-size:13px;margin-top:4px;">${file.lastModified ? new Date(file.lastModified).toLocaleDateString() : "—"}</div>
        </div>
      </div>

      <h3 style="color:#ccc;margin:16px 0 8px;">📡 Attached Sources (${file.sources?.length || 0})</h3>
      <div style="display:flex;flex-direction:column;gap:4px;">
        ${sources || '<div style="color:#666;font-size:12px;">Not attached to any sources</div>'}
      </div>

      ${scrapePages.length > 0 ? `
        <h3 style="color:#ccc;margin:16px 0 8px;">🌐 Scrape Pages (${scrapePages.length})</h3>
        <div style="background:#111;border-radius:8px;padding:12px;max-height:300px;overflow-y:auto;">
          ${pages}
        </div>
      ` : ""}
    </div>`;
}

export async function handler(
  client: CloseBotClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    if (args.fileId) {
      const [file, scrapePages] = await Promise.all([
        client.get<FileDto>(`/library/files/${args.fileId}`),
        client.get<Array<{ url?: string; enabled?: boolean }>>(`/library/files/${args.fileId}/scrape-pages`).catch(() => []),
      ]);
      const html = renderFileDetail(file, scrapePages);
      return {
        content: [{ type: "text", text: `File: ${file.fileName} (${file.fileType})` }],
        structuredContent: { type: "html", html },
      };
    }

    const files = await client.get<FileDto[]>("/library/files");
    const html = renderFileList(files);
    return {
      content: [{ type: "text", text: `Library: ${files.length} files` }],
      structuredContent: { type: "html", html },
    };
  } catch (error) {
    return err(error);
  }
}
