import { Button, buttonVariants } from '@/components/ui/button';
type ButtonProps = React.ComponentProps<typeof Button>;
type LinkProps = React.ComponentProps<typeof Link>;
import { Card as BaseCard } from '@/components/ui/card';
type CardProps = React.ComponentProps<typeof BaseCard>;
import { Tabs, TabsTrigger as Tab, TabsList } from '@/components/ui/tabs';
type TabsProps = React.ComponentProps<typeof Tabs>;
import {
  Accordion,
  AccordionItem,
  AccordionContent,
  AccordionTrigger,
} from '@/components/ui/accordion';
type AccordionProps = React.ComponentProps<typeof Accordion>;
import { Badge as Chip } from '@/components/ui/badge';
type ChipProps = React.ComponentProps<typeof Chip>;

import Link from 'next/link';
import type {
  HTMLAttributeAnchorTarget,
  HTMLAttributes,
  ReactNode,
} from 'react';
import { twMerge } from 'tailwind-merge';
import { ChevronRight as MdChevronRight} from 'lucide-react'
// import { MdChevronRight } from 'react-icons/md';
import React from 'react';
import { CheckCircle as PiCheckCircleDuotone } from 'lucide-react'
// import { PiCheckCircleDuotone } from 'react-icons/pi';
import { cn } from '@/lib/utils';

function Section({
  className,
  children,
  ...props
}: HTMLAttributes<HTMLElement>) {
  // extract the primary action and secondary action from the children
  const primaryAction = getChildComponent(children, PrimaryAction);
  const secondaryAction = getChildComponent(children, SecondaryAction);

  return (
    <section
      className={twMerge(
        'flex min-h-[400px] w-full max-w-6xl flex-col justify-center gap-2 rounded-lg px-10 py-10 md:px-20',
        className,
      )}
      {...props}
    >
      {removeFromChildren(children, [PrimaryAction, SecondaryAction])}
      <div className="mt-2 flex flex-row gap-2">
        {primaryAction}
        {secondaryAction}
      </div>
    </section>
  );
}

function Title({
  children,
  className,
  ...props
}: HTMLAttributes<HTMLHeadingElement>) {
  return (
    <h1
      {...props}
      className={twMerge(
        'text-center text-4xl font-bold md:text-6xl',
        className,
      )}
      style={{
        // @ts-ignore
        textWrap: 'balance',
      }}
    >
      {children}
    </h1>
  );
}

function Subtitle({
  children,
  className,
  ...props
}: HTMLAttributes<HTMLHeadingElement>) {
  return (
    <h2
      {...props}
      className={twMerge(
        'text text-center overflow-hidden text-ellipsis text-xl',
        className,
      )}
      style={{
        // @ts-ignore
        textWrap: 'balance',
      }}
    >
      {children}
    </h2>
  );
}

function Announcement({
  className,
  children,
  href,
  target = '_blank',
  ...props
}: ChipProps & {
  href?: string; //string | UrlObject;
  target?: HTMLAttributeAnchorTarget | undefined;
}) {
  return (
    <Chip
      className={twMerge(
        'w-fit group bg-foreground-50 text-center transition-colors hover:bg-gray-200',
        className,
      )}
      variant="outline"
      // href={href}
      // target={target}
      // as={Link}
      // endContent={
      //   <MdChevronRight
      //     size={20}
      //     className="pr-1 transition-transform group-hover:translate-x-[2px]"
      //   />
      // }
      style={{
        // @ts-ignore
        textWrap: 'balance',
      }}
      {...props}
    >
      <a href={href} target={target}>
        {children}
      </a>{' '}
      <MdChevronRight
        size={20}
        className="pr-1 transition-transform group-hover:translate-x-[2px]"
      />
    </Chip>
  );
}

type ActionProps = ButtonProps & {
  be: 'button';
  hideArrow?: boolean;
};

type ActionLinkProps = LinkProps & {
  be?: 'a';
  hideArrow?: boolean;
  variant?: ButtonProps['variant'];
};

function PrimaryAction({
  className,
  variant,
  children,
  hideArrow,
  ...props
}: ActionLinkProps | ActionProps) {
  if (props.be === 'button') {
    return (
      <Button
        className={cn(
          buttonVariants({
            variant: variant,
          }),
          'group',
          className,
        )}
        {...props}
      >
        {children}
        {!hideArrow && (
          <MdChevronRight className="transition-transform group-hover:translate-x-1" />
        )}
      </Button>
    );
  }

  return (
    <Link
      className={cn(
        buttonVariants({
          variant: variant,
        }),
        'group',
        className,
      )}
      {...props}
    >
      {children}
      {!hideArrow && (
        <MdChevronRight className="transition-transform group-hover:translate-x-1" />
      )}
    </Link>
  );
}

function SecondaryAction({
  className,
  variant,
  children,
  hideArrow,
  ...props
}: ActionLinkProps | ActionProps) {
  if (props.be === 'button') {
    return (
      <Button
        className={cn(
          buttonVariants({
            variant: variant,
          }),
          'group',
          className,
        )}
        variant={'ghost'}
        {...props}
      >
        {children}
        {!hideArrow && (
          <MdChevronRight className="transition-transform group-hover:translate-x-1" />
        )}
      </Button>
    );
  }

  return (
    <Link
      className={cn(
        buttonVariants({
          variant: 'ghost',
        }),
        'group',
        className,
      )}
      {...props}
    >
      {children}
      {!hideArrow && (
        <MdChevronRight className="transition-transform group-hover:translate-x-1" />
      )}
    </Link>
  );
}
function PricingCard({
  className,
  children,
  ...props
}: Omit<CardProps, 'children'> & {
  children:
    | ReactNode
    | ReactNode[]
    | ((pricingType: PricingType) => ReactNode | ReactNode[]);
}) {
  // const { pricingType } = usePricingContext();
  if (typeof children === 'function')
    children = (children('month') as React.ReactElement).props.children as
      | ReactNode
      | ReactNode[];

  // extract the title and subtitle from the children
  // const cardTitleStyles =
  const title = getChildComponent(children, Title, {
    className: 'text-2xl md:text-2xl text-start font-bold',
  });
  const subTitle = getChildComponent(children, Subtitle, {
    className: 'text-md text-start text-foreground-500 mt-4',
  });
  const priceTags = getChildComponents(children, PriceTag, {
    className: 'text-4xl font-bold',
  });
  const primaryAction = getChildComponent(children, PrimaryAction, {
    className: 'w-full',
  });

  return (
    <BaseCard
      // shadow="sm"
      {...props}
      className={twMerge(
        'flex flex-col min-h-[400px] w-full max-w-full items-start justify-between gap-2 p-8 text-sm',
        className,
      )}
    >
      <div>
        {title}
        {priceTags}
        {subTitle}
      </div>
      <div className="mt-4 flex h-full flex-col gap-2">
        {removeFromChildren(children, [
          Title,
          Subtitle,
          ImageArea,
          PriceTag,
          PrimaryAction,
        ]).map((item, i) => {
          return (
            <div className="flex items-center gap-2" key={i}>
              <PiCheckCircleDuotone className="text-green-600" size={20} />
              {item}
            </div>
          );
        })}
      </div>
      <div className="w-full">{primaryAction}</div>
    </BaseCard>
  );
}

// create a Pricing Context that store the monthly and pricing state
// const PricingContext = createContext<{
//   pricingType: PricingType;
//   setPricingType: (pricingType: PricingType) => void;
// }>({
//   pricingType: 'month',
//   setPricingType: (pricingType: PricingType) => {},
// });

const PricingTypeValue = ['month', 'year'] as const;
export type PricingType = (typeof PricingTypeValue)[number];

// // an helper function to useContext
// export function usePricingContext() {
//   return React.useContext(PricingContext);
// }

function Pricing({ children, ...props }: HTMLAttributes<HTMLElement>) {
  // const [pricingType, setPricingType] = useState<PricingType>('month');

  // const context = useMemo(() => {
  //   return {
  //     pricingType,
  //     setPricingType,
  //   };
  // }, [pricingType]);

  return (
    // <PricingContext.Provider value={context}>
    <Section {...props}>{children}</Section>
    // </PricingContext.Provider>
  );
}

function PricingOption({ className, ...props }: TabsProps) {
  // const { setPricingType } = usePricingContext();

  return (
    <Tabs
      className={twMerge('w-fit', className)}
      defaultValue="month"
      aria-label="Pricing Options"
      {...props}
      onValueChange={(key) => {
        // setPricingType(key as PricingType);
      }}
      // onSelectionChange={(key: any) => {
      //   setPricingType(key as PricingType);
      // }}
    >
      <TabsList>
        {PricingTypeValue.map((pricingType) => {
          return (
            <Tab
              className="capitalize"
              value={pricingType}
              key={pricingType}
              // title={}
            >
              {pricingType}
            </Tab>
          );
        })}
      </TabsList>
    </Tabs>
  );
}

function PriceTag({
  children,
  pricingType,
  ...props
}: HTMLAttributes<HTMLHeadingElement> & {
  pricingType?: 'month' | 'year' | string;
}) {
  // const { pricingType: currentPricingType } = usePricingContext();
  let currentPricingType = 'month';

  if (pricingType != undefined && currentPricingType !== pricingType)
    return <></>;

  return <h2 {...props}>{children}</h2>;
}

function Card({ className, children, ...props }: CardProps) {
  // extract the title and subtitle from the children
  // const cardTitleStyles =
  const title = getChildComponent(children, Title, {
    className: 'text-2xl md:text-2xl font-normal text-center',
  });
  const subTitle = getChildComponent(children, Subtitle, {
    className: 'text-md text-center',
  });
  const image = getChildComponent(children, ImageArea);

  return (
    <BaseCard
      // shadow="sm"
      {...props}
      className={twMerge(
        'flex min-h-[280px] w-full max-w-full items-center justify-center gap-2 p-4 text-sm flex-col',
        className,
      )}
    >
      {image}
      {title}
      {subTitle}
      {removeFromChildren(children, [Title, Subtitle, ImageArea])}
    </BaseCard>
  );
}

function ImageArea({
  className,
  children,
  ...props
}: HTMLAttributes<HTMLElement>) {
  return (
    <div
      {...props}
      className={twMerge('aspect-square w-14 bg-foreground-300', className)}
    >
      {children}
    </div>
  );
}

// create a helper to get and remove the title and subtitle from the children
function getChildComponent<T extends (...args: any[]) => React.JSX.Element>(
  children: React.ReactNode | React.ReactNode[],
  type: T,
  propsOverride?: Partial<Parameters<T>[0]>,
) {
  const childrenArr = React.Children.toArray(children);
  let child = childrenArr.find(
    (child) => React.isValidElement(child) && child.type === type,
  ) as React.ReactElement<
    Parameters<T>[0],
    string | React.JSXElementConstructor<any>
  >;

  if (child && propsOverride) {
    const { className, ...rest } = child.props;
    child = React.cloneElement(child, {
      className: twMerge(className, propsOverride.className),
      ...rest,
    });
  }

  return child;
}

function getChildComponents<T extends (...args: any[]) => React.JSX.Element>(
  children: React.ReactNode | React.ReactNode[],
  type: T,
  propsOverride?: Partial<Parameters<T>[0]>,
) {
  const childrenArr = React.Children.toArray(children);
  let child = (
    childrenArr.filter(
      (child) => React.isValidElement(child) && child.type === type,
    ) as React.ReactElement<
      Parameters<T>[0],
      string | React.JSXElementConstructor<any>
    >[]
  ).map((child) => {
    if (child && propsOverride) {
      const { className, ...rest } = child.props;
      child = React.cloneElement(child, {
        className: twMerge(className, propsOverride.className),
        ...rest,
      });
    }
    return child;
  });

  return child;
}

function removeFromChildren(
  children: React.ReactNode | React.ReactNode[],
  types: any[],
): React.ReactNode[] {
  return React.Children.toArray(children).filter(
    (child) => React.isValidElement(child) && !types.includes(child.type),
  );
}

function FAQ({ children, ...props }: AccordionProps) {
  return <Accordion {...props}>{children}</Accordion>;
}

function FAQItem({
  children,
  ...props
}: {
  children: React.ReactNode | React.ReactNode[];
  'aria-label': string;
  title: string;
}): JSX.Element {
  return (
    <AccordionItem value={props['aria-label']}>
      <AccordionTrigger>{props.title}</AccordionTrigger>
      <AccordionContent>{children}</AccordionContent>
    </AccordionItem>
  );
}

// const FAQItem = AccordionItem;

const pkg = Object.assign(Section, {
  Pricing,
  PricingOption,
  Title,
  Subtitle,
  Announcement,
  PrimaryAction,
  SecondaryAction,
  ImageArea,
  Card,
  FAQItem,
  FAQ,
  PricingCard,
  PriceTag,
});

export { pkg as Section };
