import React, { useMemo } from "react";
import { useEffect, useState } from "react";
import { create } from "zustand";
import { useDashboard } from "../../layouts/Dashboard/useDashboard";
import { useBackend } from "../../layouts/Wrapper";
import { twMerge } from "tailwind-merge";
import { useMaxHeight } from "../../lib/useMaxHeight";
import { Title, Text } from "../../tremor/Text";
import { DataSource, WidgetSuggestion } from "@onvo-ai/js";
import { Badge } from "../../tremor/Badge";
import { Button } from "../../tremor/Button";
import { PlusIcon, TrashIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { Popover, PopoverContent, PopoverTrigger } from "../../tremor/Popover";
import { Tooltip } from "../../tremor/Tooltip";
import { Icon } from "../../tremor/Icon";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "../../tremor/Tabs";
import { WidgetLibrary } from "../WidgetLibrary";
import { Card } from "../../tremor/Card";

export const useWidgetSuggestionsModal = create<{
  open: boolean;
  setOpen: (
    open: boolean,
  ) => void;
  suggestions: WidgetSuggestion[];
  setSuggestions: (
    suggestions: WidgetSuggestion[],
  ) => void;
}>((set) => ({
  open: false,
  setOpen: (
    op: boolean,
  ) => set({ open: op }),
  suggestions: [],
  setSuggestions: (
    suggestions: WidgetSuggestion[],
  ) => set({ suggestions: suggestions }),
}));


const generateDatasourceHash = async (datasources: DataSource[]) => {
  const ids = datasources.map(a => a.id).sort().join(",");
  const encoder = new TextEncoder();
  const data = encoder.encode(ids);

  // Compute SHA-256 hash
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);

  // Convert ArrayBuffer -> hex string
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, "0")).join("");

  // Truncate to desired length
  return hashHex.slice(0, 16);
}

export const WidgetSuggestionsModal: React.FC<{}> = ({ }) => {
  const { dashboard, refreshWidgets, tab, datasources } = useDashboard();
  const { backend, adminMode, containerRef } = useBackend();
  const { open, setOpen, suggestions, setSuggestions } = useWidgetSuggestionsModal();
  const { lg, sm } = useMaxHeight();
  const [loading, setLoading] = useState(true);
  const [generating, setGenerating] = useState(false);
  const [hash, setHash] = useState("");
  const [adding, setAdding] = useState<{ [id: string]: boolean }>({});
  const [deleting, setDeleting] = useState<{ [id: string]: boolean }>({});

  useEffect(() => {
    if (!dashboard || !backend) return;
    generateDatasourceHash(datasources).then((h) => setHash(h));
  }, [dashboard, datasources]);

  const createWidget = async (suggestion: WidgetSuggestion) => {
    if (!dashboard || !backend) return;
    setAdding({ ...adding, [suggestion.id]: true });
    let widget = await backend.widgets.create({
      dashboard: dashboard.id,
      layouts: {
        lg: {
          x: 0,
          y: lg,
          w: 4,
          h: suggestion.type === "metric" ? 8 : 20,
        },
        sm: {
          x: 0,
          y: sm,
          w: 3,
          h: suggestion.type === "metric" ? 8 : 20,
        },
      },
      use_in_library: false,
      use_in_chat: false,
      title: suggestion.title || "",
      team: dashboard.team,
      code: "",
      messages: [],
      settings: {},
      error: null,
      tab: tab || 0,
      config: {},
      engine: "python-v1",
      type: suggestion.type || "metric",
      drilldown_widget: null,
    });

    refreshWidgets(backend);
    await backend.dashboard(dashboard.id).widgetSuggestions.delete(suggestion.id);
    setSuggestions(suggestions.filter((s) => s.id !== suggestion.id));
    await backend.widget(widget.id).updatePrompts([{
      role: "user",
      content: suggestion.description || "",
    }]);

    refreshWidgets(backend);
    setAdding({ ...adding, [suggestion.id]: false });
  }

  const getWidgetSuggestions = async () => {
    if (!dashboard || !backend || !adminMode) return;
    setLoading(true);
    const suggestions = await backend.dashboard(dashboard.id).widgetSuggestions.list();
    setLoading(false);
    setSuggestions(suggestions);
  }

  const generateWidgetSuggestions = async (clearExisting?: boolean) => {
    if (!dashboard || !backend) return;
    setGenerating(true);
    if (clearExisting) {
      await Promise.all(suggestions.filter((s) => s.datasource_hash !== hash).map((s) => backend.dashboard(dashboard.id).widgetSuggestions.delete(s.id)));
    }
    await backend.dashboard(dashboard.id).generateWidgetSuggestions();
    setGenerating(false);
    getWidgetSuggestions();
  }

  const clearWidgetSuggestion = async (id: string) => {
    if (!dashboard || !backend) return;
    setDeleting({ ...deleting, [id]: true });
    await backend.dashboard(dashboard.id).widgetSuggestions.delete(id);
    getWidgetSuggestions();
    setDeleting({ ...deleting, [id]: false });
  }

  useEffect(() => {
    getWidgetSuggestions();
  }, [dashboard, adminMode, backend]);

  const hashMismatch = useMemo(() => {
    let mismatch = false;
    suggestions.forEach((s) => {
      if (s.datasource_hash !== hash) {
        mismatch = true;
      }
    });
    return mismatch;
  }, [hash, suggestions]);

  const AddToDashboardEnabled = useMemo(() => {
    if (adminMode) return true;
    if (dashboard?.settings?.can_create_widgets) return true;
    return false;
  }, [dashboard, adminMode]);

  if (!adminMode) return <></>;

  return (
    <div className={twMerge(
      "onvo-@container/widgetmodal onvo-h-full !onvo-w-full onvo-z-40 onvo-background-color onvo-flex onvo-flex-col onvo-relative"
    )}
    >

      <Tabs defaultValue="suggestions" className="onvo-h-full onvo-relative">
        <div className="onvo-py-3 onvo-relative">
          <TabsList className="onvo-flex-grow">
            <TabsTrigger value="suggestions">Suggestions</TabsTrigger>
            <TabsTrigger value="library">Library</TabsTrigger>
          </TabsList>

          <div className="onvo-absolute onvo-top-2 onvo-right-2 onvo-rounded-full onvo-transition-all onvo-size-7 onvo-bg-black/5 dark:onvo-bg-white/5 onvo-flex onvo-items-center onvo-justify-center onvo-cursor-pointer hover:onvo-bg-black/10 dark:hover:onvo-bg-white/10">
            <XMarkIcon className="onvo-size-4 onvo-text-blank dark:onvo-text-white" onClick={() => setOpen(false)} />
          </div>
        </div>
        <TabsContent value="suggestions" className="onvo-px-3 onvo-py-0 onvo-overflow-y-auto onvo-h-[calc(100%-45px)]">

          <div className="onvo-flex-grow onvo-px-0 onvo-flex onvo-flex-col onvo-gap-2">

            {!loading && hashMismatch && (
              <div className="onvo-flex onvo-flex-row onvo-justify-center onvo-my-2 onvo-items-center onvo-gap-4 onvo-rounded-2xl onvo-bg-blue-500/20 onvo-py-3 onvo-px-4">
                <Text>Your datasources have changed since the last time you generated widget suggestions. Please generate new suggestions.</Text>
                <Button variant="secondary" isLoading={generating} onClick={() => generateWidgetSuggestions(true)}>Regenerate</Button>
              </div>
            )}

            {suggestions.filter((suggestion) => suggestion.datasource_hash === hash).map((suggestion) => (
              <Card className="onvo-py-0 onvo-px-0 onvo-flex onvo-flex-col onvo-gap-2 onvo-justify-between onvo-items-center" key={suggestion.id}>
                <div className="onvo-flex-grow onvo-py-4 onvo-px-4 ">
                  <div className="onvo-flex onvo-flex-row onvo-gap-2 onvo-items-center">
                    <Title className="!onvo-text-sm">{suggestion.title}</Title>
                    <Badge className="!onvo-py-0.5">{suggestion.type}</Badge>
                  </div>
                  <Text className="onvo-mt-1">{suggestion.description}</Text>
                </div>


                <div className="onvo-chart-card-dropdown-wrapper onvo-flex-grow onvo-flex-shrink-0 onvo-py-2 onvo-px-2 onvo-z-20 onvo-border-solid onvo-border-t onvo-border-black/5 dark:onvo-border-white/10 onvo-rounded-b-2xl onvo-background-color onvo-flex onvo-w-full onvo-justify-between onvo-flex-row onvo-items-center">
                  <div className="onvo-flex onvo-gap-2 onvo-items-center">
                    {adminMode && (
                      <Button
                        variant="ghost" isLoading={deleting[suggestion.id]}
                        onClick={() => clearWidgetSuggestion(suggestion.id)}
                      >
                        Remove suggestion
                      </Button>
                    )}
                  </div>
                  <div className="onvo-flex onvo-gap-2 onvo-items-center">
                    {AddToDashboardEnabled && (
                      <Button
                        isLoading={adding[suggestion.id]}
                        variant="secondary" className="onvo-foreground-color onvo-border-black/10 dark:onvo-border-white/10"
                        onClick={() => createWidget(suggestion)}
                      >
                        Add to dashboard
                      </Button>
                    )}
                  </div>
                </div>
              </Card>
            ))}
            {!loading && !hashMismatch && (
              <div className="onvo-py-2 onvo-flex onvo-justify-center onvo-items-center">
                {suggestions.length >= 30 ? (
                  <Tooltip content="You can only have a maximum of 30 widget suggestions">
                    <Button variant="secondary" className="onvo-my-2" disabled>Generate more suggestions</Button>
                  </Tooltip>
                ) : (
                  <Button variant="secondary" className="onvo-mt-2 onvo-mb-4" isLoading={generating} onClick={() => generateWidgetSuggestions(false)}>Generate more suggestions</Button>
                )}
              </div>
            )}
          </div>
        </TabsContent>
        <TabsContent value="library" className="onvo-px-3 onvo-py-0">
          <WidgetLibrary
            onClose={() => setOpen(false)}
          />
        </TabsContent>
      </Tabs>
    </div>

  );
};
