"use client";

import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/__legacy__/ui/popover";
import { ScrollArea } from "@/components/__legacy__/ui/scroll-area";
import { Text } from "@/components/atoms/Text/Text";
import useCredits from "@/hooks/useCredits";
import {
  OnboardingStep,
  WebSocketNotification,
} from "@/lib/autogpt-server-api";
import { cn } from "@/lib/utils";
import { useOnboarding } from "@/providers/onboarding/onboarding-provider";
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
import { WalletIcon } from "@phosphor-icons/react";
import { PopoverClose } from "@radix-ui/react-popover";
import { X } from "lucide-react";
import * as party from "party-js";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { WalletRefill } from "./components/WalletRefill";
import { TaskGroups } from "./components/WalletTaskGroups";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";

export interface Task {
  id: OnboardingStep;
  name: string;
  amount: number;
  details: string;
  video?: string;
  progress?: {
    current: number;
    target: number;
  };
}

export interface TaskGroup {
  name: string;
  details: string;
  tasks: Task[];
}

export function Wallet() {
  const { state, updateState } = useOnboarding();
  const isPaymentEnabled = useGetFlag(Flag.ENABLE_PLATFORM_PAYMENT);

  const groups = useMemo<TaskGroup[]>(() => {
    return [
      {
        name: "First Wins",
        details: "Kickstart your journey with quick wins.",
        tasks: [
          {
            id: "GET_RESULTS",
            name: "Complete onboarding and see your first agent's results",
            amount: 3,
            details: "",
          },
          {
            id: "MARKETPLACE_VISIT",
            name: "Go to Marketplace",
            amount: 1,
            details: "Click Marketplace in the top navigation",
            video: "/onboarding/marketplace-visit.mp4",
          },
          {
            id: "MARKETPLACE_ADD_AGENT",
            name: "Find and add an agent",
            amount: 1,
            details:
              "Search for an agent in the Marketplace and add it to your Library",
            video: "/onboarding/marketplace-add.mp4",
          },
          {
            id: "MARKETPLACE_RUN_AGENT",
            name: "Open the Library page and run an agent",
            amount: 1,
            details: "Go to the Library, open an agent you want, and run it",
            video: "/onboarding/marketplace-run.mp4",
          },
          {
            id: "BUILDER_SAVE_AGENT",
            name: "Place your first blocks and save your agent",
            amount: 1,
            details:
              "Open block library on the left and add a block to the canvas then save your agent",
            video: "/onboarding/builder-save.mp4",
          },
        ],
      },
      {
        name: "Consistency Challenge",
        details: "Build your rhythm and make agents part of your routine.",
        tasks: [
          {
            id: "RE_RUN_AGENT",
            name: "Re-run an agent",
            amount: 1,
            details: "Re-run an agent from the Library",
          },
          {
            id: "SCHEDULE_AGENT",
            name: "Schedule your first agent",
            amount: 1,
            details: "Schedule an agent to run on a recurring basis",
          },
          {
            id: "RUN_AGENTS",
            name: "Run 10 agents",
            amount: 3,
            details: "Run agents from Library or Builder 10 times",
            progress: {
              current: state?.agentRuns || 0,
              target: 10,
            },
          },
          {
            id: "RUN_3_DAYS",
            name: "Run agents 3 days in a row",
            amount: 1,
            details:
              "Run any agents from the Library or Builder for 3 days in a row",
            progress: {
              current: state?.consecutiveRunDays || 0,
              target: 3,
            },
          },
        ],
      },
      {
        name: "The Pro Playground",
        details: "Master powerful features to supercharge your workflow.",
        tasks: [
          {
            id: "TRIGGER_WEBHOOK",
            name: "Trigger an agent via webhook",
            amount: 1,
            details:
              "In the Builder, go to Settings and copy the Webhook URL. Use it to trigger your agent from another app.",
          },
          {
            id: "RUN_14_DAYS",
            name: "Run agents 14 days in a row",
            amount: 3,
            details:
              "Run any agents from the Library or Builder for 10 days in a row",
            progress: {
              current: state?.consecutiveRunDays || 0,
              target: 14,
            },
          },
          {
            id: "RUN_AGENTS_100",
            name: "Complete 100 agent runs",
            amount: 3,
            details: "Let your agents run and complete 100 tasks in total",
            progress: {
              current: state?.agentRuns || 0,
              target: 100,
            },
          },
        ],
      },
    ];
  }, [state]);

  const api = useBackendAPI();
  const { credits, formatCredits, fetchCredits } = useCredits({
    fetchInitialCredits: true,
  });

  const [prevCredits, setPrevCredits] = useState<number | null>(credits);
  const [flash, setFlash] = useState(false);
  const [walletOpen, setWalletOpen] = useState(false);

  const totalCount = useMemo(() => {
    return groups.reduce((acc, group) => acc + group.tasks.length, 0);
  }, [groups]);

  // Total completed task count across all groups
  const [completedCount, setCompletedCount] = useState<number | null>(null);

  const walletRef = useRef<HTMLButtonElement | null>(null);

  useEffect(() => {
    if (!state) {
      return;
    }
    const completed = groups.reduce(
      (acc, group) =>
        acc +
        group.tasks.filter((task) => state?.completedSteps?.includes(task.id))
          .length,
      0,
    );
    setCompletedCount(completed);
  }, [groups, state?.completedSteps]);

  const onWalletOpen = useCallback(async () => {
    if (!state?.walletShown) {
      updateState({ walletShown: true });
    }
    // Refresh credits when the wallet is opened
    fetchCredits();
  }, [state?.walletShown, updateState, fetchCredits]);

  const fadeOut = useMemo(
    () =>
      new party.ModuleBuilder()
        .drive("opacity")
        .by((t) => 1 - t)
        .through("lifetime")
        .build(),
    [],
  );

  // React to onboarding notifications emitted by the provider
  const handleNotification = useCallback(
    (notification: WebSocketNotification) => {
      if (
        notification.type !== "onboarding" ||
        notification.event !== "step_completed"
      ) {
        return;
      }

      // Always refresh credits when any onboarding step completes
      fetchCredits();

      // Only trigger confetti for tasks that are in displayed groups
      if (!walletRef.current) {
        return;
      }
      const taskIds = groups
        .flatMap((group) => group.tasks)
        .map((task) => task.id);
      if (!taskIds.includes(notification.step as OnboardingStep)) {
        return;
      }

      const rect = walletRef.current.getBoundingClientRect();
      if (rect.width === 0 || rect.height === 0) {
        return;
      }

      party.confetti(walletRef.current, {
        count: 30,
        spread: 120,
        shapes: ["square", "circle"],
        size: party.variation.range(1, 2),
        speed: party.variation.range(200, 300),
        modules: [fadeOut],
      });
    },
    [fetchCredits, fadeOut, groups],
  );

  // WebSocket setup for onboarding notifications
  useEffect(() => {
    const detachMessage = api.onWebSocketMessage(
      "notification",
      handleNotification,
    );

    api.connectWebSocket();

    return () => {
      detachMessage();
    };
  }, [api, handleNotification]);

  // Wallet flash on credits change
  useEffect(() => {
    if (credits === prevCredits) {
      return;
    }
    setPrevCredits(credits);
    if (prevCredits === null) {
      return;
    }
    setFlash(true);
    setTimeout(() => {
      setFlash(false);
    }, 300);
  }, [credits, prevCredits]);

  // Do not render until we have both credits and onboarding data
  if (credits === null || !state) return null;

  return (
    <Popover open={walletOpen} onOpenChange={(open) => setWalletOpen(open)}>
      <PopoverTrigger asChild>
        <div className="relative inline-block">
          <button
            ref={walletRef}
            className="group relative flex flex-nowrap items-center gap-2 rounded-md bg-zinc-50 px-3 py-2 text-sm"
            onClick={onWalletOpen}
          >
            <WalletIcon size={20} className="inline-block md:hidden" />
            <div>
              <span className="mr-1 hidden md:inline-block">Earn credits </span>
              <span className="text-sm font-semibold">
                {formatCredits(credits)}
              </span>
              {completedCount !== null && completedCount < totalCount && (
                <span className="absolute right-1 top-1 h-2 w-2 rounded-full bg-violet-600"></span>
              )}
              <div className="absolute bottom-[-2.5rem] left-1/2 z-50 hidden -translate-x-1/2 transform whitespace-nowrap rounded-small bg-white px-4 py-2 shadow-md group-hover:block">
                <Text variant="body-medium">
                  {completedCount} of {totalCount} rewards claimed
                </Text>
              </div>
            </div>
          </button>
          <div
            className={cn(
              "pointer-events-none absolute inset-0 rounded-md bg-violet-400 duration-2000 ease-in-out",
              flash ? "opacity-50 duration-0" : "opacity-0",
            )}
          />
        </div>
      </PopoverTrigger>
      <PopoverContent
        side="bottom"
        align="end"
        collisionPadding={16}
        className={cn("relative -top-12 z-50 w-[28.5rem] px-[0.625rem] py-2")}
      >
        {/* Header */}
        <div className="mx-1 flex items-center justify-between border-b border-zinc-200 pb-3">
          <span className="font-poppins font-medium text-zinc-900">
            Your credits
          </span>
          <div className="flex items-center text-sm text-violet-700">
            <div className="rounded-lg bg-violet-100 px-3 py-2">
              Earn credits{" "}
              <span className="font-semibold">{formatCredits(credits)}</span>
            </div>
            <PopoverClose aria-label="Close wallet">
              <X className="ml-2 h-5 w-5 text-zinc-800 hover:text-foreground" />
            </PopoverClose>
          </div>
        </div>
        <ScrollArea className="max-h-[85vh] overflow-y-auto">
          {/* Top ups */}
          {isPaymentEnabled && <WalletRefill />}
          {/* Tasks */}
          <p className="mx-1 my-3 font-sans text-xs font-normal text-zinc-400">
            Complete the following tasks to earn more credits!
          </p>
          <TaskGroups groups={groups} />
        </ScrollArea>
      </PopoverContent>
    </Popover>
  );
}
