"use client";

// Frontend Tools (Async) demo.
//
// Same `useFrontendTool` pattern as `frontend-tools`, but the handler is
// async and awaits a simulated client-side DB round-trip. The full async
// path is exercised end-to-end: agent invokes -> handler awaits -> result
// returned -> branded render.

import React from "react";
import {
  CopilotKitProvider,
  CopilotChat,
  useFrontendTool,
  useConfigureSuggestions,
} from "@copilotkit/react-core/v2";
import { z } from "zod";
import { NotesCard, type Note } from "./notes-card";

// Fake client-side "notes database". In a real app this could be an
// IndexedDB, a fetched local cache, or any other client-owned data store.
const NOTES_DB: Note[] = [
  {
    id: "n1",
    title: "Q2 project planning kickoff",
    excerpt:
      "Discussed scope for the new onboarding flow with design. Draft spec due Friday.",
    tags: ["planning", "project", "onboarding"],
  },
  {
    id: "n2",
    title: "Planning: migrate auth to passkeys",
    excerpt:
      "Research WebAuthn library options. Consider fallback for unsupported browsers.",
    tags: ["planning", "auth", "security"],
  },
  {
    id: "n3",
    title: "Grocery list",
    excerpt: "Olive oil, tomatoes, sourdough, basil, parmesan.",
    tags: ["personal", "shopping"],
  },
  {
    id: "n4",
    title: "Book recommendations",
    excerpt:
      "Thinking Fast and Slow (Kahneman); The Design of Everyday Things (Norman).",
    tags: ["reading"],
  },
  {
    id: "n5",
    title: "Project planning retrospective notes",
    excerpt:
      "What went well: async standups. What didn't: ambiguous ownership on shared components.",
    tags: ["retro", "project", "planning"],
  },
  {
    id: "n6",
    title: "Weekend hike plan",
    excerpt: "Tam West Peak → Rock Spring. 8mi loop, bring layers.",
    tags: ["personal", "outdoors"],
  },
  {
    id: "n7",
    title: "1:1 prep — career planning",
    excerpt: "Discuss growth areas. Ask about scope for Q3. Revisit goals doc.",
    tags: ["career", "planning"],
  },
];

function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function parseJsonResult<T>(result: unknown): T {
  if (!result) return {} as T;
  try {
    return (typeof result === "string" ? JSON.parse(result) : result) as T;
  } catch {
    return {} as T;
  }
}

export default function FrontendToolsAsyncDemo() {
  return (
    <CopilotKitProvider runtimeUrl="/api/copilotkit" useSingleEndpoint>
      <div className="flex justify-center items-center h-screen w-full">
        <div className="h-full w-full max-w-4xl">
          <Chat />
        </div>
      </div>
    </CopilotKitProvider>
  );
}

function Chat() {
  // @region[frontend-tool-async]
  // @region[frontend-tool-async-registration]
  useFrontendTool({
    name: "query_notes",
    description:
      "Search the user's local notes database for notes whose title, " +
      "excerpt, or tags contain the given keyword (case-insensitive). " +
      "Returns up to 5 matching notes.",
    parameters: z.object({
      keyword: z
        .string()
        .describe("Keyword or phrase to search notes for (case-insensitive)."),
    }),
    // @region[frontend-tool-async-handler]
    // Async handler: awaits a simulated client-side DB round-trip (500ms)
    // and returns the matching notes. The agent then uses the returned
    // result to summarize what it found — exercising the full async
    // frontend-tool path end-to-end.
    handler: async ({ keyword }: { keyword: string }) => {
      await sleep(500);
      const q = keyword.toLowerCase();
      const matches = NOTES_DB.filter((n) => {
        return (
          n.title.toLowerCase().includes(q) ||
          n.excerpt.toLowerCase().includes(q) ||
          (n.tags ?? []).some((t) => t.toLowerCase().includes(q))
        );
      }).slice(0, 5);
      return {
        keyword,
        count: matches.length,
        notes: matches,
      };
    },
    // @endregion[frontend-tool-async-handler]
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    render: ({ args, result, status }: any) => {
      const loading = status !== "complete";
      const parsed = parseJsonResult<{
        keyword?: string;
        count?: number;
        notes?: Note[];
      }>(result);
      return (
        <NotesCard
          loading={loading}
          keyword={args?.keyword ?? parsed.keyword ?? ""}
          notes={parsed.notes}
        />
      );
    },
  });
  // @endregion[frontend-tool-async-registration]
  // @endregion[frontend-tool-async]

  useConfigureSuggestions({
    suggestions: [
      {
        title: "Find project-planning notes",
        message: "Find my notes about project planning.",
      },
      {
        title: "Search for 'auth'",
        message: "Search my notes for anything related to auth.",
      },
      {
        title: "What do I have about reading?",
        message: "Do I have any notes tagged reading?",
      },
    ],
    available: "always",
  });

  return <CopilotChat className="h-full rounded-2xl" />;
}
