"use client";

import * as React from "react";
import { cn } from "../../lib/utils";
import { Button } from "./button";
import { Input } from "./input";
import { Label } from "./label";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "./popover";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs";
import { Slider } from "./slider";
import { cva, type VariantProps } from "class-variance-authority";
import { motion, AnimatePresence } from "framer-motion";
import { Copy, Check, Palette, Pipette } from "lucide-react";

/**
 * ColorPicker Component
 * 
 * A comprehensive color picker with multiple input methods
 */

const colorPickerVariants = cva(
  "relative inline-flex items-center justify-center",
  {
    variants: {
      size: {
        default: "h-10 w-10",
        sm: "h-8 w-8",
        lg: "h-12 w-12",
        xl: "h-16 w-16",
      },
      shape: {
        square: "rounded-md",
        circle: "rounded-full",
        rounded: "rounded-lg",
      },
    },
    defaultVariants: {
      size: "default",
      shape: "square",
    },
  }
);

// Color utilities
function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result
    ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16),
      }
    : null;
}

function rgbToHex(r: number, g: number, b: number): string {
  return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}

function hexToHsl(hex: string): { h: number; s: number; l: number } | null {
  const rgb = hexToRgb(hex);
  if (!rgb) return null;

  const r = rgb.r / 255;
  const g = rgb.g / 255;
  const b = rgb.b / 255;

  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  let h = 0;
  let s = 0;
  const l = (max + min) / 2;

  if (max !== min) {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r:
        h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
        break;
      case g:
        h = ((b - r) / d + 2) / 6;
        break;
      case b:
        h = ((r - g) / d + 4) / 6;
        break;
    }
  }

  return {
    h: Math.round(h * 360),
    s: Math.round(s * 100),
    l: Math.round(l * 100),
  };
}

function hslToHex(h: number, s: number, l: number): string {
  h = h / 360;
  s = s / 100;
  l = l / 100;

  let r, g, b;

  if (s === 0) {
    r = g = b = l;
  } else {
    const hue2rgb = (p: number, q: number, t: number) => {
      if (t < 0) t += 1;
      if (t > 1) t -= 1;
      if (t < 1 / 6) return p + (q - p) * 6 * t;
      if (t < 1 / 2) return q;
      if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
      return p;
    };

    const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    const p = 2 * l - q;
    r = hue2rgb(p, q, h + 1 / 3);
    g = hue2rgb(p, q, h);
    b = hue2rgb(p, q, h - 1 / 3);
  }

  return rgbToHex(
    Math.round(r * 255),
    Math.round(g * 255),
    Math.round(b * 255)
  );
}

export interface ColorPickerProps
  extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange" | "value">,
    VariantProps<typeof colorPickerVariants> {
  /**
   * Current color value
   */
  value?: string;
  /**
   * Callback when color changes
   */
  onChange?: (color: string) => void;
  /**
   * Show color input
   */
  showInput?: boolean;
  /**
   * Show preset colors
   */
  showPresets?: boolean;
  /**
   * Preset colors
   */
  presets?: string[];
  /**
   * Allow opacity
   */
  allowOpacity?: boolean;
  /**
   * Color format
   */
  format?: "hex" | "rgb" | "hsl";
  /**
   * Disable copy button
   */
  disableCopy?: boolean;
  /**
   * Trigger mode
   */
  triggerMode?: "click" | "hover";
}

// Default preset colors
const defaultPresets = [
  "#000000", "#ffffff", "#ff0000", "#00ff00", "#0000ff",
  "#ffff00", "#ff00ff", "#00ffff", "#ff8800", "#8800ff",
  "#88ff00", "#0088ff", "#ff0088", "#00ff88", "#888888",
  "#f87171", "#fb923c", "#fbbf24", "#facc15", "#a3e635",
  "#4ade80", "#34d399", "#2dd4bf", "#22d3ee", "#38bdf8",
  "#60a5fa", "#818cf8", "#a78bfa", "#c084fc", "#e879f9",
  "#f472b6", "#fb7185", "#f43f5e", "#ef4444", "#dc2626",
];

export function ColorPicker({
  className,
  size,
  shape,
  value = "#000000",
  onChange,
  showInput = true,
  showPresets = true,
  presets = defaultPresets,
  allowOpacity = false,
  format = "hex",
  disableCopy = false,
  triggerMode = "click",
  disabled,
  ...props
}: ColorPickerProps) {
  const [open, setOpen] = React.useState(false);
  const [color, setColor] = React.useState(value);
  const [opacity, setOpacity] = React.useState(100);
  const [copied, setCopied] = React.useState(false);
  const [inputValue, setInputValue] = React.useState(value);

  // Color components
  const hsl = React.useMemo(() => hexToHsl(color) || { h: 0, s: 0, l: 0 }, [color]);
  const rgb = React.useMemo(() => hexToRgb(color) || { r: 0, g: 0, b: 0 }, [color]);

  React.useEffect(() => {
    setColor(value);
    setInputValue(value);
  }, [value]);

  const handleColorChange = (newColor: string) => {
    setColor(newColor);
    setInputValue(newColor);
    onChange?.(newColor);
  };

  const handleHslChange = (component: "h" | "s" | "l", value: number) => {
    const newHsl = { ...hsl, [component]: value };
    const newColor = hslToHex(newHsl.h, newHsl.s, newHsl.l);
    handleColorChange(newColor);
  };

  const handleRgbChange = (component: "r" | "g" | "b", value: number) => {
    const newRgb = { ...rgb, [component]: value };
    const newColor = rgbToHex(newRgb.r, newRgb.g, newRgb.b);
    handleColorChange(newColor);
  };

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newValue = e.target.value;
    setInputValue(newValue);
    if (/^#[0-9A-F]{6}$/i.test(newValue)) {
      handleColorChange(newValue);
    }
  };

  const copyToClipboard = async () => {
    try {
      let textToCopy = color;
      if (format === "rgb") {
        textToCopy = `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
      } else if (format === "hsl") {
        textToCopy = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
      }
      await navigator.clipboard.writeText(textToCopy);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (err) {
      console.error("Failed to copy:", err);
    }
  };

  const formatDisplay = () => {
    if (format === "rgb") return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
    if (format === "hsl") return `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
    return color;
  };

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          className={cn(
            colorPickerVariants({ size, shape }),
            "p-0 border-2",
            className
          )}
          style={{ backgroundColor: color }}
          disabled={disabled}
          {...props}
        >
          <span className="sr-only">Pick a color</span>
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-80" align="start" sideOffset={8}>
        <Tabs defaultValue="picker" className="w-full">
          <TabsList className="grid w-full grid-cols-3">
            <TabsTrigger value="picker">Picker</TabsTrigger>
            <TabsTrigger value="sliders">Sliders</TabsTrigger>
            <TabsTrigger value="input">Input</TabsTrigger>
          </TabsList>

          <TabsContent value="picker" className="space-y-4">
            {/* Color gradient picker */}
            <div className="relative h-48 rounded-md overflow-hidden">
              <div
                className="absolute inset-0"
                style={{
                  background: `linear-gradient(to right, #fff, hsl(${hsl.h}, 100%, 50%))`,
                }}
              />
              <div
                className="absolute inset-0"
                style={{
                  background: "linear-gradient(to bottom, transparent, #000)",
                }}
              />
              <motion.div
                className="absolute w-4 h-4 border-2 border-white rounded-full shadow-md cursor-pointer"
                drag
                dragConstraints={{
                  left: -8,
                  right: 280,
                  top: -8,
                  bottom: 184,
                }}
                dragElastic={0}
                style={{
                  backgroundColor: color,
                  left: `${(hsl.s / 100) * 280 - 8}px`,
                  top: `${(1 - hsl.l / 100) * 192 - 8}px`,
                }}
              />
            </div>

            {/* Hue slider */}
            <div className="space-y-2">
              <Label>Hue</Label>
              <div
                className="relative h-3 rounded-full"
                style={{
                  background:
                    "linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)",
                }}
              >
                <Slider
                  value={[hsl.h]}
                  onValueChange={([value]) => handleHslChange("h", value)}
                  max={360}
                  step={1}
                  className="absolute inset-0"
                />
              </div>
            </div>

            {/* Opacity slider */}
            {allowOpacity && (
              <div className="space-y-2">
                <Label>Opacity</Label>
                <div className="flex items-center gap-3">
                  <Slider
                    value={[opacity]}
                    onValueChange={([value]) => setOpacity(value)}
                    max={100}
                    step={1}
                    className="flex-1"
                  />
                  <span className="text-sm w-10 text-right">{opacity}%</span>
                </div>
              </div>
            )}
          </TabsContent>

          <TabsContent value="sliders" className="space-y-4">
            {/* RGB Sliders */}
            <div className="space-y-3">
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <Label>Red</Label>
                  <span className="text-sm text-muted-foreground">{rgb.r}</span>
                </div>
                <Slider
                  value={[rgb.r]}
                  onValueChange={([value]) => handleRgbChange("r", value)}
                  max={255}
                  step={1}
                  className="[&_[role=slider]]:bg-red-500"
                />
              </div>
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <Label>Green</Label>
                  <span className="text-sm text-muted-foreground">{rgb.g}</span>
                </div>
                <Slider
                  value={[rgb.g]}
                  onValueChange={([value]) => handleRgbChange("g", value)}
                  max={255}
                  step={1}
                  className="[&_[role=slider]]:bg-green-500"
                />
              </div>
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <Label>Blue</Label>
                  <span className="text-sm text-muted-foreground">{rgb.b}</span>
                </div>
                <Slider
                  value={[rgb.b]}
                  onValueChange={([value]) => handleRgbChange("b", value)}
                  max={255}
                  step={1}
                  className="[&_[role=slider]]:bg-blue-500"
                />
              </div>
            </div>

            {/* HSL Info */}
            <div className="pt-2 border-t">
              <div className="grid grid-cols-3 gap-2 text-sm">
                <div>
                  <p className="text-muted-foreground">H</p>
                  <p className="font-medium">{hsl.h}°</p>
                </div>
                <div>
                  <p className="text-muted-foreground">S</p>
                  <p className="font-medium">{hsl.s}%</p>
                </div>
                <div>
                  <p className="text-muted-foreground">L</p>
                  <p className="font-medium">{hsl.l}%</p>
                </div>
              </div>
            </div>
          </TabsContent>

          <TabsContent value="input" className="space-y-4">
            <div className="space-y-2">
              <Label>Hex Color</Label>
              <div className="flex gap-2">
                <Input
                  value={inputValue}
                  onChange={handleInputChange}
                  placeholder="#000000"
                  className="font-mono"
                />
                <Button
                  size="icon"
                  variant="outline"
                  onClick={() => handleColorChange(inputValue)}
                >
                  <Check className="h-4 w-4" />
                </Button>
              </div>
            </div>

            <div className="space-y-2">
              <Label>RGB Values</Label>
              <div className="grid grid-cols-3 gap-2">
                <Input
                  type="number"
                  value={rgb.r}
                  onChange={(e) => handleRgbChange("r", parseInt(e.target.value) || 0)}
                  min={0}
                  max={255}
                  className="text-center"
                />
                <Input
                  type="number"
                  value={rgb.g}
                  onChange={(e) => handleRgbChange("g", parseInt(e.target.value) || 0)}
                  min={0}
                  max={255}
                  className="text-center"
                />
                <Input
                  type="number"
                  value={rgb.b}
                  onChange={(e) => handleRgbChange("b", parseInt(e.target.value) || 0)}
                  min={0}
                  max={255}
                  className="text-center"
                />
              </div>
            </div>
          </TabsContent>
        </Tabs>

        {/* Color preview and copy */}
        <div className="mt-4 flex items-center justify-between p-3 border rounded-lg">
          <div className="flex items-center gap-3">
            <div
              className={cn(
                "h-10 w-10 rounded border-2",
                colorPickerVariants({ shape })
              )}
              style={{ backgroundColor: color }}
            />
            <div>
              <p className="text-sm font-medium">{formatDisplay()}</p>
              <p className="text-xs text-muted-foreground">Current color</p>
            </div>
          </div>
          {!disableCopy && (
            <Button
              size="icon"
              variant="ghost"
              onClick={copyToClipboard}
              className="h-8 w-8"
            >
              <AnimatePresence mode="wait">
                {copied ? (
                  <motion.div
                    key="check"
                    initial={{ scale: 0 }}
                    animate={{ scale: 1 }}
                    exit={{ scale: 0 }}
                  >
                    <Check className="h-4 w-4 text-green-600" />
                  </motion.div>
                ) : (
                  <motion.div
                    key="copy"
                    initial={{ scale: 0 }}
                    animate={{ scale: 1 }}
                    exit={{ scale: 0 }}
                  >
                    <Copy className="h-4 w-4" />
                  </motion.div>
                )}
              </AnimatePresence>
            </Button>
          )}
        </div>

        {/* Preset colors */}
        {showPresets && presets.length > 0 && (
          <div className="mt-4 space-y-2">
            <Label>Preset Colors</Label>
            <div className="grid grid-cols-10 gap-1">
              {presets.map((presetColor) => (
                <button
                  key={presetColor}
                  className={cn(
                    "h-7 w-7 rounded border-2 transition-all hover:scale-110",
                    color === presetColor
                      ? "border-primary"
                      : "border-transparent"
                  )}
                  style={{ backgroundColor: presetColor }}
                  onClick={() => handleColorChange(presetColor)}
                />
              ))}
            </div>
          </div>
        )}
      </PopoverContent>
    </Popover>
  );
}

/**
 * SimpleColorPicker Component
 * 
 * A simplified color picker with preset colors only
 */

export interface SimpleColorPickerProps {
  value?: string;
  onChange?: (color: string) => void;
  colors?: string[];
  className?: string;
  size?: "sm" | "default" | "lg";
}

export function SimpleColorPicker({
  value = "#000000",
  onChange,
  colors = defaultPresets.slice(0, 10),
  className,
  size = "default",
}: SimpleColorPickerProps) {
  const sizeClasses = {
    sm: "h-6 w-6",
    default: "h-8 w-8",
    lg: "h-10 w-10",
  };

  return (
    <div className={cn("moonui-theme", "flex flex-wrap gap-2", className)}>
      {colors.map((color) => (
        <button
          key={color}
          className={cn(
            "rounded-full border-2 transition-all hover:scale-110",
            sizeClasses[size],
            value === color ? "border-primary ring-2 ring-primary/20" : "border-transparent"
          )}
          style={{ backgroundColor: color }}
          onClick={() => onChange?.(color)}
        />
      ))}
    </div>
  );
}

/**
 * GradientPicker Component
 * 
 * Pick gradient colors
 */

export interface GradientPickerProps {
  value?: { start: string; end: string; angle?: number };
  onChange?: (gradient: { start: string; end: string; angle: number }) => void;
  className?: string;
}

export function GradientPicker({
  value = { start: "#ff0000", end: "#0000ff", angle: 90 },
  onChange,
  className,
}: GradientPickerProps) {
  const [gradient, setGradient] = React.useState(value);

  const handleChange = (field: "start" | "end" | "angle", newValue: string | number) => {
    const newGradient = { ...gradient, [field]: newValue };
    setGradient(newGradient);
    onChange?.(newGradient as { start: string; end: string; angle: number });
  };

  return (
    <div className={cn("moonui-theme", "space-y-4", className)}>
      <div
        className="h-20 rounded-lg border-2"
        style={{
          background: `linear-gradient(${gradient.angle}deg, ${gradient.start}, ${gradient.end})`,
        }}
      />
      
      <div className="grid grid-cols-2 gap-4">
        <div className="space-y-2">
          <Label>Start Color</Label>
          <ColorPicker
            value={gradient.start}
            onChange={(color) => handleChange("start", color)}
            size="sm"
          />
        </div>
        <div className="space-y-2">
          <Label>End Color</Label>
          <ColorPicker
            value={gradient.end}
            onChange={(color) => handleChange("end", color)}
            size="sm"
          />
        </div>
      </div>
      
      <div className="space-y-2">
        <div className="flex items-center justify-between">
          <Label>Angle</Label>
          <span className="text-sm text-muted-foreground">{gradient.angle}°</span>
        </div>
        <Slider
          value={[gradient.angle || 90]}
          onValueChange={([value]) => handleChange("angle", value)}
          max={360}
          step={1}
        />
      </div>
    </div>
  );
}

// Re-export icons used
export { Palette, Pipette } from "lucide-react";