import { useMemo, useState } from "react";
import { Button } from "@/components/ui/button";
import { Copy, Check, Heart } from "lucide-react";
import { ThemeEditorState } from "@/types/editor";
import { ScrollArea, ScrollBar } from "../ui/scroll-area";
import { CodeBlock } from "@/components/ai-elements/code-block";
import {
  Tabs,
  TabsList,
  TabsTrigger,
  TabsContent,
  TabsIndicator,
} from "@/components/ui/base-ui-tabs";
import {
  Select,
  SelectContent,
  SelectTrigger,
  SelectValue,
  SelectItem,
} from "@/components/ui/select";
import { usePostHog } from "posthog-js/react";
import { useEditorStore } from "@/store/editor-store";
import { usePreferencesStore } from "@/store/preferences-store";
import {
  generateThemeCode,
  generateTailwindConfigCode,
  generateLayoutCode,
} from "@/utils/theme-style-generator";
import { useThemePresetStore } from "@/store/theme-preset-store";
import { useDialogActions } from "@/hooks/use-dialog-actions";
import { ColorFormat } from "@/types";

interface CodePanelProps {
  themeEditorState: ThemeEditorState;
  themeId?: string;
}

const CodePanel: React.FC<CodePanelProps> = ({ themeEditorState, themeId }) => {
  const [registryCopied, setRegistryCopied] = useState(false);
  const [copied, setCopied] = useState(false);
  const [activeTab, setActiveTab] = useState<string>("index.css");
  const posthog = usePostHog();
  const { handleSaveClick } = useDialogActions();

  const preset = useEditorStore((state) => state.themeState.preset);
  const colorFormat = usePreferencesStore((state) => state.colorFormat);
  const tailwindVersion = usePreferencesStore((state) => state.tailwindVersion);
  const packageManager = usePreferencesStore((state) => state.packageManager);
  const setColorFormat = usePreferencesStore((state) => state.setColorFormat);
  const setTailwindVersion = usePreferencesStore((state) => state.setTailwindVersion);
  const setPackageManager = usePreferencesStore((state) => state.setPackageManager);
  const hasUnsavedChanges = useEditorStore((state) => state.hasUnsavedChanges);

  const isSavedPreset = useThemePresetStore(
    (state) => preset && state.getPreset(preset)?.source === "SAVED"
  );
  const getAvailableColorFormats = usePreferencesStore((state) => state.getAvailableColorFormats);

  const code = generateThemeCode(themeEditorState, colorFormat, tailwindVersion);
  const configCode = generateTailwindConfigCode(themeEditorState, colorFormat, tailwindVersion);
  const layoutCode = generateLayoutCode(themeEditorState);

  const getRegistryCommand = (id: string, isSaved: boolean) => {
    const url = isSaved
      ? `https://tweakcn.com/r/themes/${id}`
      : `https://tweakcn.com/r/themes/${id}.json`;
    switch (packageManager) {
      case "pnpm":
        return `pnpm dlx shadcn@latest add ${url}`;
      case "npm":
        return `npx shadcn@latest add ${url}`;
      case "yarn":
        return `yarn dlx shadcn@latest add ${url}`;
      case "bun":
        return `bunx shadcn@latest add ${url}`;
    }
  };

  const registryId = themeId ?? preset;
  const isRegistrySaved = !!themeId || !!isSavedPreset;

  const copyRegistryCommand = async () => {
    try {
      await navigator.clipboard.writeText(getRegistryCommand(registryId ?? "default", isRegistrySaved));
      setRegistryCopied(true);
      setTimeout(() => setRegistryCopied(false), 2000);
      captureCopyEvent("COPY_REGISTRY_COMMAND");
    } catch (err) {
      console.error("Failed to copy text:", err);
    }
  };

  const captureCopyEvent = (event: string) => {
    posthog.capture(event, {
      editorType: "theme",
      preset,
      colorFormat,
      tailwindVersion,
    });
  };

  const copyToClipboard = async (text: string) => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
      captureCopyEvent("COPY_CODE");
    } catch (err) {
      console.error("Failed to copy text:", err);
    }
  };

  const showRegistryCommand = useMemo(() => {
    if (themeId) return true;
    return preset && preset !== "default" && !hasUnsavedChanges();
  }, [themeId, preset, hasUnsavedChanges]);

  const PackageManagerHeader = ({ actionButton }: { actionButton: React.ReactNode }) => (
    <div className="flex border-b">
      {(["pnpm", "npm", "yarn", "bun"] as const).map((pm) => (
        <button
          key={pm}
          onClick={() => setPackageManager(pm)}
          className={`px-3 py-1.5 text-sm font-medium ${
            packageManager === pm
              ? "bg-muted text-foreground"
              : "text-muted-foreground hover:text-foreground"
          }`}
        >
          {pm}
        </button>
      ))}
      {actionButton}
    </div>
  );

  return (
    <div className="flex h-full flex-col">
      <div className="mb-4 flex-none">
        <div className="flex items-center justify-between gap-2">
          <h2 className="text-lg font-semibold">Theme Code</h2>
        </div>
        <div className="mt-4 overflow-hidden rounded-md border">
          <PackageManagerHeader
            actionButton={
              showRegistryCommand ? (
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={copyRegistryCommand}
                  className="ml-auto h-8"
                  aria-label={registryCopied ? "Copied to clipboard" : "Copy to clipboard"}
                >
                  {registryCopied ? <Check className="size-4" /> : <Copy className="size-4" />}
                </Button>
              ) : (
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => handleSaveClick()}
                  className="ml-auto h-8 gap-1"
                  aria-label="Save theme"
                >
                  <Heart className="size-4" />
                  <span className="sr-only sm:not-sr-only">Save</span>
                </Button>
              )
            }
          />
          <div className="bg-muted/50 flex items-center justify-between p-2">
            {showRegistryCommand ? (
              <ScrollArea className="w-full">
                <div className="overflow-y-hidden pb-2 whitespace-nowrap">
                  <code className="font-mono text-sm">{getRegistryCommand(registryId as string, isRegistrySaved)}</code>
                </div>
                <ScrollBar orientation="horizontal" />
              </ScrollArea>
            ) : (
              <div className="text-muted-foreground text-sm">
                Save your theme to get the registry command
              </div>
            )}
          </div>
        </div>
      </div>
      <div className="mb-4 flex items-center gap-2">
        <Select
          value={tailwindVersion}
          onValueChange={(value: "3" | "4") => {
            setTailwindVersion(value);
            if (value === "4" && colorFormat === "hsl") {
              setColorFormat("oklch");
            }
            if (activeTab === "tailwind.config.ts") {
              setActiveTab("index.css");
            }
          }}
        >
          <SelectTrigger className="bg-muted/50 w-fit gap-1 border-none outline-hidden focus:border-none focus:ring-transparent">
            <SelectValue className="focus:ring-transparent" />
          </SelectTrigger>
          <SelectContent className="z-99999">
            <SelectItem value="3">Tailwind v3</SelectItem>
            <SelectItem value="4">Tailwind v4</SelectItem>
          </SelectContent>
        </Select>
        <Select value={colorFormat} onValueChange={(value: ColorFormat) => setColorFormat(value)}>
          <SelectTrigger className="bg-muted/50 w-fit gap-1 border-none outline-hidden focus:border-none focus:ring-transparent">
            <SelectValue className="focus:ring-transparent" />
          </SelectTrigger>
          <SelectContent className="z-99999">
            {getAvailableColorFormats().map((colorFormat) => (
              <SelectItem key={colorFormat} value={colorFormat}>
                {colorFormat}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>
      <Tabs
        value={activeTab}
        onValueChange={setActiveTab}
        defaultValue="index.css"
        className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg border"
      >
        <div className="bg-muted/50 flex flex-none items-center justify-between border-b px-4 py-2">
          <TabsList className="h-8 bg-transparent p-0">
            <TabsTrigger value="index.css" className="h-7 px-3 text-sm font-medium">
              index.css
            </TabsTrigger>
            {tailwindVersion === "3" && (
              <TabsTrigger value="tailwind.config.ts" className="h-7 px-3 text-sm font-medium">
                tailwind.config.ts
              </TabsTrigger>
            )}
            <TabsTrigger value="layout.tsx" className="h-7 px-3 text-sm font-medium">
              layout.tsx (Next.js)
            </TabsTrigger>
            <TabsIndicator className="bg-background rounded-sm" />
          </TabsList>

          <div className="flex items-center gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() =>
                copyToClipboard(
                  activeTab === "index.css"
                    ? code
                    : activeTab === "layout.tsx"
                      ? layoutCode
                      : configCode
                )
              }
              className="h-8"
              aria-label={copied ? "Copied to clipboard" : "Copy to clipboard"}
            >
              {copied ? (
                <>
                  <Check className="size-4" />
                  <span className="sr-only md:not-sr-only">Copied</span>
                </>
              ) : (
                <>
                  <Copy className="size-4" />
                  <span className="sr-only md:not-sr-only">Copy</span>
                </>
              )}
            </Button>
          </div>
        </div>

        <TabsContent value="index.css" className="overflow-hidden">
          <ScrollArea className="relative h-full">
            <CodeBlock code={code} language="css" className="h-full rounded-none border-0" />
            <ScrollBar orientation="horizontal" />
            <ScrollBar orientation="vertical" />
          </ScrollArea>
        </TabsContent>

        {tailwindVersion === "3" && (
          <TabsContent value="tailwind.config.ts" className="overflow-hidden">
            <ScrollArea className="relative h-full">
              <CodeBlock
                code={configCode}
                language="typescript"
                className="h-full rounded-none border-0"
              />
              <ScrollBar orientation="horizontal" />
              <ScrollBar orientation="vertical" />
            </ScrollArea>
          </TabsContent>
        )}

        <TabsContent value="layout.tsx" className="overflow-hidden">
          <ScrollArea className="relative h-full">
            <CodeBlock
              code={layoutCode}
              language="tsx"
              className="h-full rounded-none border-0"
            />
            <ScrollBar orientation="horizontal" />
            <ScrollBar orientation="vertical" />
          </ScrollArea>
        </TabsContent>
      </Tabs>
    </div>
  );
};

export default CodePanel;