'use client';

import { HTMLAttributes, ReactNode, useState } from 'react';

import { cn } from '@/lib/helper';
import Image from 'next/image';
import Collapse from '@/components/Collapse';
import { Icon } from '@iconify/react';

export interface CardProps
  extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {
  title?: string;
  subtitle?: string;
  image?: string;
  imageAlt?: string;
  imageWidth?: number;
  imageHeight?: number;
  actions?: ReactNode;
  footer?: ReactNode;
  collapsible?: boolean;
  defaultCollapsed?: boolean;
  onCollapsedChange?: (collapsed: boolean) => void;
  className?: {
    wrapper?: string;
    wrapperContent?: string;
    image?: string;
    body?: string;
    title?: string;
    subtitle?: string;
    actions?: string;
    footer?: string;
    collapsible?: string;
  };
  variant?: 'default' | 'compact' | 'bordered' | 'shadow' | 'image-full';
  size?: 'sm' | 'md' | 'lg';
}

const Card = ({
  title,
  subtitle,
  image,
  imageAlt,
  imageWidth,
  imageHeight,
  actions,
  footer,
  collapsible,
  defaultCollapsed = false,
  onCollapsedChange,
  className,
  variant = 'default',
  size = 'md',
  children,
  ...props
}: CardProps) => {
  const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);

  const handleCollapsedChange = (open: boolean) => {
    const collapsed = !open;
    setIsCollapsed(collapsed);
    onCollapsedChange?.(collapsed);
  };

  const getCardClasses = () => {
    const baseClasses = 'card bg-base-100';

    const variantClasses = {
      default: '',
      compact: 'card-compact',
      bordered: 'border border-base-300',
      shadow: 'shadow-xl',
      'image-full': 'card-side card-compact shadow-xl',
    };

    const sizeClasses = {
      sm: 'w-64',
      md: 'w-96',
      lg: 'w-[28rem]',
    };

    return cn(
      baseClasses,
      variantClasses[variant],
      variant !== 'image-full' ? sizeClasses[size] : '',
      className?.wrapper
    );
  };

  const getImageDimensions = () => {
    if (variant === 'image-full') {
      return {
        width: imageWidth || 128,
        height: imageHeight || 128,
      };
    }

    const cardWidths = {
      sm: 256, // w-64
      md: 384, // w-96
      lg: 448, // w-[28rem]
    };

    return {
      width: imageWidth || cardWidths[size],
      height: imageHeight || 192,
    };
  };

  const getImageClasses = () => {
    if (variant === 'image-full') {
      return cn('object-cover', className?.image);
    }
    return cn('w-full object-cover', className?.image);
  };

  const getBodyClasses = () => {
    const baseClasses = 'card-body';

    if (variant === 'compact' || variant === 'image-full') {
      return cn(baseClasses, 'p-4', className?.body);
    }

    return cn(baseClasses, 'p-6', className?.body);
  };

  const getCollapsibleClasses = () => {
    return cn('', className?.collapsible);
  };

  const getTitleClasses = () => {
    const sizeClasses = {
      sm: 'text-lg',
      md: 'text-xl',
      lg: 'text-2xl',
    };

    return cn('card-title font-bold', sizeClasses[size], className?.title);
  };

  const getSubtitleClasses = () => {
    return cn('text-base-content/70 text-sm mt-1', className?.subtitle);
  };

  const getActionsClasses = () => {
    return cn('card-actions justify-end mt-4', className?.actions);
  };

  const getFooterClasses = () => {
    return cn('border-t border-base-300 mt-4 pt-4', className?.footer);
  };

  const getWrapperContentClasses = () => {
    return cn('space-y-4', className?.wrapperContent);
  };

  const renderCardContent = () => {
    const hasContent = children || actions || footer;

    const titleContent = (
      <div
        className={
          `group flex items-center justify-between! w-full` + getTitleClasses()
        }
      >
        <div className='flex-1'>
          {title && <h2 className={getTitleClasses()}>{title}</h2>}
          {subtitle && <p className={getSubtitleClasses()}>{subtitle}</p>}
        </div>
        {collapsible && (
          <button
            onClick={() => handleCollapsedChange(!isCollapsed)}
            className={`btn btn-ghost btn-sm btn-circle` + getTitleClasses()}
            aria-label={isCollapsed ? 'Expand content' : 'Collapse content'}
          >
            <Icon
              icon={
                isCollapsed
                  ? 'material-symbols:expand-more'
                  : 'material-symbols:expand-less'
              }
              width={20}
            />
          </button>
        )}
      </div>
    );

    const cardContent = (
      <div className={getWrapperContentClasses()}>
        {children}
        {actions && <div className={getActionsClasses()}>{actions}</div>}
        {footer && <div className={getFooterClasses()}>{footer}</div>}
      </div>
    );

    return (
      <>
        {image && (
          <figure>
            <Image
              src={image}
              alt={imageAlt || title || 'Card image'}
              width={getImageDimensions().width}
              height={getImageDimensions().height}
              className={getImageClasses()}
            />
          </figure>
        )}
        <div className={getBodyClasses()}>
          {collapsible && hasContent ? (
            <Collapse
              variant='default'
              bordered={false}
              open={!isCollapsed}
              onOpenChange={handleCollapsedChange}
              title={titleContent}
              titleClassName='w-full cursor-pointer'
              contentClassName='p-0'
              fullWidth={true}
              className={getCollapsibleClasses()}
            >
              {cardContent}
            </Collapse>
          ) : (
            <>
              {(title || subtitle) && (
                <div className='mb-4'>
                  {title && <h2 className={getTitleClasses()}>{title}</h2>}
                  {subtitle && (
                    <p className={getSubtitleClasses()}>{subtitle}</p>
                  )}
                </div>
              )}
              {hasContent && cardContent}
            </>
          )}
        </div>
      </>
    );
  };

  if (variant === 'image-full' && image) {
    return (
      <div className={getCardClasses()} {...props}>
        {renderCardContent()}
      </div>
    );
  }

  return (
    <div className={getCardClasses()} {...props}>
      {renderCardContent()}
    </div>
  );
};

export default Card;
