import React, {
  createContext,
  ForwardedRef,
  forwardRef,
  useContext,
  useImperativeHandle,
} from 'react';
import {Pressable, View} from 'react-native';
import {IconChevronDown, IconChevronUp} from '@tabler/icons-react-native';
import {Avatar} from '@components/_HuGo/Avatar';
import {Pill} from '@components/_HuGo/Pill';
import {Title} from '@components/_HuGo/Title';
import {useCollapsed} from '@hooks/useCollapsed';
import {useTheme} from '@shared/theme';
import {commonStyles} from '@shared/styles';

import {styles} from './styles';
import {
  AccordionContextValue,
  AccordionRef,
  AccordionProps,
  AccordionHeaderProps,
  AccordionContentProps,
  AccordionTitleProps,
  AccordionIconProps,
  AccordionAvatarProps,
  AccordionPillProps,
} from './interfaces';

const AccordionContext = createContext<Nullable<AccordionContextValue>>(null);

export const useAccordionContext = () => {
  const context = useContext(AccordionContext);

  if (!context) {
    throw new Error('Accordion components must be used within an Accordion');
  }

  return context;
};

function AccordionForwardRef(
  {
    children,
    initialCollapsed = false,
    withBackground = true,
    style,
    disabled = false,
  }: AccordionProps,
  ref: ForwardedRef<AccordionRef>,
) {
  const {theme} = useTheme();
  const {
    collapsed: isCollapsed,
    onToggleCollapsed,
    onSetCollapsed,
  } = useCollapsed(initialCollapsed);

  useImperativeHandle(ref, () => ({
    setCollapsed: () => {
      onSetCollapsed(initialCollapsed);
    },
    isCollapsed,
  }));

  const contextValue: AccordionContextValue = {
    isCollapsed,
    onToggleCollapsed,
    disabled,
  };

  return (
    <AccordionContext.Provider value={contextValue}>
      <View
        style={[
          styles.container,
          withBackground && {
            backgroundColor: theme.background.elements.default,
          },
          style,
        ]}>
        {children}
      </View>
    </AccordionContext.Provider>
  );
}

function AccordionHeader({children, style, onPress}: AccordionHeaderProps) {
  const {spacing} = useTheme();
  const {onToggleCollapsed, disabled} = useAccordionContext();

  return (
    <Pressable
      hitSlop={spacing.x1}
      style={[styles.header, style]}
      onPress={onPress ?? onToggleCollapsed}
      disabled={disabled}>
      {children}
    </Pressable>
  );
}

function AccordionContent({children, style}: AccordionContentProps) {
  const {isCollapsed} = useAccordionContext();

  return !isCollapsed ? null : (
    <View style={[styles.content, style]}>{children}</View>
  );
}

function AccordionTitle({
  title,
  description,
  topText,
  titleNumberOfLines = 2,
  descriptionNumberOfLines = 5,
  style,
}: AccordionTitleProps) {
  return (
    <Title
      size="s"
      title={title}
      titleNumberOfLines={titleNumberOfLines}
      description={description}
      descriptionNumberOfLines={descriptionNumberOfLines}
      topText={topText}
      style={[commonStyles.flex, style]}
    />
  );
}

function AccordionIcon({style, onPress}: AccordionIconProps) {
  const {iconSizes, theme} = useTheme();
  const {isCollapsed, disabled, onToggleCollapsed} = useAccordionContext();
  const IconComponent = isCollapsed ? IconChevronUp : IconChevronDown;

  return disabled ? null : (
    <Pressable style={style} onPress={onPress ?? onToggleCollapsed}>
      <IconComponent size={iconSizes.x6} color={theme.text.neutral.default} />
    </Pressable>
  );
}

function AccordionAvatar({style, ...avatarProps}: AccordionAvatarProps) {
  return (
    <View style={style}>
      <Avatar {...avatarProps} />
    </View>
  );
}

function AccordionPill({style, ...pillProps}: AccordionPillProps) {
  return (
    <View style={style}>
      <Pill {...pillProps} />
    </View>
  );
}

export const Accordion = forwardRef(
  AccordionForwardRef,
) as React.ForwardRefExoticComponent<
  AccordionProps & React.RefAttributes<AccordionRef>
> & {
  Header: typeof AccordionHeader;
  Content: typeof AccordionContent;
  Title: typeof AccordionTitle;
  Icon: typeof AccordionIcon;
  Avatar: typeof AccordionAvatar;
  Pill: typeof AccordionPill;
};

Accordion.Header = AccordionHeader;
Accordion.Content = AccordionContent;
Accordion.Title = AccordionTitle;
Accordion.Icon = AccordionIcon;
Accordion.Avatar = AccordionAvatar;
Accordion.Pill = AccordionPill;

export type {AccordionRef, AccordionProps} from './interfaces';
