"use client";

import * as React from "react";
import { ChevronDown } from "lucide-react";
import { cn } from "@/lib/utils";

interface AccordionContextValue {
  value: string[];
  onValueChange: (value: string[]) => void;
}

const AccordionContext = React.createContext<AccordionContextValue | undefined>(
  undefined
);

interface AccordionProps {
  type?: "single" | "multiple";
  defaultValue?: string | string[];
  value?: string | string[];
  onValueChange?: (value: string | string[]) => void;
  children: React.ReactNode;
  className?: string;
}

const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(
  ({ type = "single", defaultValue, value, onValueChange, children, className }, ref) => {
    const [internalValue, setInternalValue] = React.useState<string[]>(
      defaultValue
        ? Array.isArray(defaultValue)
          ? defaultValue
          : [defaultValue]
        : []
    );

    const controlledValue = value
      ? Array.isArray(value)
        ? value
        : [value]
      : undefined;

    const currentValue = controlledValue ?? internalValue;

    const handleValueChange = React.useCallback(
      (newValue: string[]) => {
        if (!controlledValue) {
          setInternalValue(newValue);
        }
        if (onValueChange) {
          onValueChange(type === "single" ? newValue[0] || "" : newValue);
        }
      },
      [controlledValue, onValueChange, type]
    );

    const contextValue = React.useMemo(
      () => ({
        value: currentValue,
        onValueChange: handleValueChange,
      }),
      [currentValue, handleValueChange]
    );

    return (
      <AccordionContext.Provider value={contextValue}>
        <div ref={ref} className={cn("space-y-2", className)}>
          {children}
        </div>
      </AccordionContext.Provider>
    );
  }
);
Accordion.displayName = "Accordion";

interface AccordionItemProps {
  value: string;
  children: React.ReactNode;
  className?: string;
}

const AccordionItem = React.forwardRef<HTMLDivElement, AccordionItemProps>(
  ({ value, children, className }, ref) => {
    return (
      <div
        ref={ref}
        className={cn("rounded-xl border border-gray-200 overflow-hidden", className)}
        data-value={value}
      >
        {children}
      </div>
    );
  }
);
AccordionItem.displayName = "AccordionItem";

interface AccordionTriggerProps {
  children: React.ReactNode;
  className?: string;
}

const AccordionTrigger = React.forwardRef<
  HTMLButtonElement,
  AccordionTriggerProps
>(({ children, className }, ref) => {
  const context = React.useContext(AccordionContext);
  if (!context) {
    throw new Error("AccordionTrigger must be used within Accordion");
  }

  const item = React.useContext(ItemContext);
  if (!item) {
    throw new Error("AccordionTrigger must be used within AccordionItem");
  }

  const isOpen = context.value.includes(item.value);

  const handleClick = () => {
    const newValue = isOpen
      ? context.value.filter((v) => v !== item.value)
      : [...context.value, item.value];
    context.onValueChange(newValue);
  };

  return (
    <button
      ref={ref}
      type="button"
      onClick={handleClick}
      className={cn(
        "flex w-full items-center justify-between p-4 text-left font-medium text-primary transition-all hover:bg-secondary [&[data-state=open]>svg]:rotate-180",
        className
      )}
      data-state={isOpen ? "open" : "closed"}
    >
      {children}
      <ChevronDown className="h-5 w-5 shrink-0 transition-transform duration-200" />
    </button>
  );
});
AccordionTrigger.displayName = "AccordionTrigger";

interface AccordionContentProps {
  children: React.ReactNode;
  className?: string;
}

const ItemContext = React.createContext<{ value: string } | undefined>(
  undefined
);

const AccordionContent = React.forwardRef<
  HTMLDivElement,
  AccordionContentProps
>(({ children, className }, ref) => {
  const context = React.useContext(AccordionContext);
  if (!context) {
    throw new Error("AccordionContent must be used within Accordion");
  }

  const item = React.useContext(ItemContext);
  if (!item) {
    throw new Error("AccordionContent must be used within AccordionItem");
  }

  const isOpen = context.value.includes(item.value);

  return (
    <div
      ref={ref}
      className={cn(
        "overflow-hidden transition-all",
        isOpen ? "max-h-[1000px] opacity-100" : "max-h-0 opacity-0"
      )}
    >
      <div className={cn("p-4 pt-0 text-gray-700", className)}>
        {children}
      </div>
    </div>
  );
});
AccordionContent.displayName = "AccordionContent";

const AccordionItemWithContext = React.forwardRef<
  HTMLDivElement,
  AccordionItemProps
>(({ value, children, ...props }, ref) => {
  return (
    <ItemContext.Provider value={{ value }}>
      <AccordionItem ref={ref} value={value} {...props}>
        {children}
      </AccordionItem>
    </ItemContext.Provider>
  );
});
AccordionItemWithContext.displayName = "AccordionItem";

export {
  Accordion,
  AccordionItemWithContext as AccordionItem,
  AccordionTrigger,
  AccordionContent,
};

