import { type ReactNode } from 'react';

import { Box, Stack, Typography } from '@mui/material';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import {
  IconBell,
  IconBriefcase,
  IconCheck,
  IconHeart,
  IconInfoCircle,
  IconStar,
  IconUser,
} from '@tabler/icons-react';

import ImgAvatar1 from '../../../../static/avatar1.png';

import { type AvatarProps } from './types';
import Avatar from '.';

const SAMPLE_IMAGE = ImgAvatar1;
const BROKEN_IMAGE = 'https://example.com/nonexistent-image.png';

const COLORS: NonNullable<AvatarProps['color']>[] = [
  'default',
  'white',
  'primary',
  'highlight',
  'success',
  'error',
  'warning',
  'info',
];

const SIZES: NonNullable<AvatarProps['size']>[] = ['small', 'medium', 'large'];

const SIZE_PIXELS: Record<NonNullable<AvatarProps['size']>, string> = {
  small: '32',
  medium: '40',
  large: '60',
};

const SHAPES: NonNullable<AvatarProps['variant']>[] = [
  'circular',
  'rounded',
  'square',
];

type ShowcaseProps = {
  label: string;
  children: ReactNode;
};

const Showcase = ({ label, children }: ShowcaseProps) => (
  <Stack sx={{ alignItems: 'center', gap: 1, minWidth: 80 }}>
    <Box
      sx={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        minHeight: 60,
      }}
    >
      {children}
    </Box>
    <Typography
      variant="globalXS"
      color="text.secondary"
      sx={{ textTransform: 'capitalize' }}
    >
      {label}
    </Typography>
  </Stack>
);

type SectionProps = {
  title: string;
  children: ReactNode;
};

const Section = ({ title, children }: SectionProps) => (
  <Stack sx={{ gap: 2 }}>
    <Typography
      variant="globalS"
      fontWeight="fontWeightSemiBold"
      color="text.primary"
    >
      {title}
    </Typography>
    <Stack
      direction="row"
      sx={{ gap: 3, flexWrap: 'wrap', alignItems: 'flex-end' }}
    >
      {children}
    </Stack>
  </Stack>
);

const meta: Meta<typeof Avatar> = {
  component: Avatar,
  title: 'Design System/Avatars/Avatar',
  tags: ['autodocs'],
  parameters: {
    docs: {
      description: {
        component:
          'Displays a user or entity avatar. Renders an image when `src` is provided, falls back to ' +
          '`text` (initials), then to an `Icon` (default: IconUser). Supports three sizes, three ' +
          'shape variants, eight colour variants, an optional badge, disabled and loading states.',
      },
    },
  },
  argTypes: {
    src: {
      description: 'Image URL. Takes priority over `text` and `Icon`.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    text: {
      description:
        'Fallback text (e.g. initials) shown when `src` is not available.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    Icon: {
      description:
        'Fallback icon shown when neither `src` nor `text` is available.',
      control: false,
      table: {
        type: { summary: 'TablerIcon' },
        defaultValue: { summary: 'IconUser' },
      },
    },
    alt: {
      description: 'Alt text for the image.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    size: {
      description:
        'Avatar dimensions: small (32px), medium (40px), large (60px).',
      control: 'inline-radio',
      options: SIZES,
      table: {
        type: { summary: "'small' | 'medium' | 'large'" },
        defaultValue: { summary: "'medium'" },
      },
    },
    variant: {
      description:
        'Shape of the avatar. Also determines the skeleton shape when loading.',
      control: 'inline-radio',
      options: SHAPES,
      table: {
        type: { summary: "'circular' | 'rounded' | 'square'" },
      },
    },
    color: {
      description:
        'Background/foreground colour variant applied to the fallback state.',
      control: 'select',
      options: COLORS,
      table: {
        type: {
          summary:
            "'white' | 'default' | 'primary' | 'highlight' | 'success' | 'error' | 'warning' | 'info'",
        },
        defaultValue: { summary: "'default'" },
      },
    },
    loading: {
      description:
        'When true, renders a Skeleton placeholder matching the configured size and variant.',
      control: { type: 'boolean' },
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    disabled: {
      description: 'If true, reduces opacity and disables pointer events.',
      control: { type: 'boolean' },
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    withBadge: {
      description: 'If true, wraps the avatar with a Badge.',
      control: { type: 'boolean' },
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    badgeProps: {
      description:
        'Props forwarded to the Badge component. `badgeContent` controls the number; ' +
        '`variant` is forced to `dot` for small avatars or when no content is provided.',
      control: 'object',
      table: { type: { summary: 'BadgeProps' } },
    },
    onClick: {
      description: 'Click handler for the avatar.',
      control: false,
      table: { type: { summary: '(event: React.MouseEvent) => void' } },
    },
    sx: {
      description: 'MUI `sx` style overrides applied to the inner MUI Avatar.',
      control: false,
      table: { type: { summary: 'SxProps' } },
    },
  },
  args: {
    src: SAMPLE_IMAGE,
    alt: 'Sofía Fernández',
    text: 'SF',
    variant: 'circular',
    size: 'medium',
    color: 'default',
  },
};

export default meta;

type Story = StoryObj<typeof Avatar>;

/**
 * Playground story. Use the controls panel to explore every prop and combine
 * them freely.
 */
export const Playground: Story = {
  args: {},
};

/**
 * Eight semantic colour variants intended for the *fallback* states (initials
 * and icon). Colours are not applied when a valid `src` is rendered.
 */
export const Colors: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Stack sx={{ gap: 4 }}>
      <Section title="With initials">
        {COLORS.map(color => (
          <Showcase
            key={`text-${color}`}
            label={color}
          >
            <Avatar
              text="SF"
              color={color}
            />
          </Showcase>
        ))}
      </Section>
      <Section title="With icon">
        {COLORS.map(color => (
          <Showcase
            key={`icon-${color}`}
            label={color}
          >
            <Avatar
              Icon={IconUser}
              color={color}
            />
          </Showcase>
        ))}
      </Section>
    </Stack>
  ),
};

/**
 * Three avatar dimensions. Icon and initials are scaled accordingly to stay
 * legible at every size.
 */
export const Sizes: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Stack sx={{ gap: 4 }}>
      <Section title="Image">
        {SIZES.map(size => (
          <Showcase
            key={`img-${size}`}
            label={`${size} (${SIZE_PIXELS[size]}px)`}
          >
            <Avatar
              src={SAMPLE_IMAGE}
              alt="User"
              size={size}
            />
          </Showcase>
        ))}
      </Section>
      <Section title="Initials">
        {SIZES.map(size => (
          <Showcase
            key={`text-${size}`}
            label={size}
          >
            <Avatar
              text="SF"
              color="primary"
              size={size}
            />
          </Showcase>
        ))}
      </Section>
      <Section title="Icon">
        {SIZES.map(size => (
          <Showcase
            key={`icon-${size}`}
            label={size}
          >
            <Avatar
              Icon={IconUser}
              color="highlight"
              size={size}
            />
          </Showcase>
        ))}
      </Section>
    </Stack>
  ),
};

/**
 * Shape variants: `circular`, `rounded`, and `square`. The same shape is used
 * for the loading skeleton.
 */
export const Shapes: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Stack sx={{ gap: 4 }}>
      <Section title="Image">
        {SHAPES.map(variant => (
          <Showcase
            key={`img-${variant}`}
            label={variant}
          >
            <Avatar
              src={SAMPLE_IMAGE}
              alt="User"
              variant={variant}
            />
          </Showcase>
        ))}
      </Section>
      <Section title="Initials">
        {SHAPES.map(variant => (
          <Showcase
            key={`text-${variant}`}
            label={variant}
          >
            <Avatar
              text="SF"
              color="primary"
              variant={variant}
            />
          </Showcase>
        ))}
      </Section>
      <Section title="Icon">
        {SHAPES.map(variant => (
          <Showcase
            key={`icon-${variant}`}
            label={variant}
          >
            <Avatar
              Icon={IconUser}
              color="highlight"
              variant={variant}
            />
          </Showcase>
        ))}
      </Section>
    </Stack>
  ),
};

/**
 * Fallback hierarchy: `src` → `text` (initials) → `Icon`. When the image fails
 * to load (or is omitted) the avatar gracefully falls back through each level.
 */
export const Fallbacks: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Section title="Fallback hierarchy">
      <Showcase label="src (image)">
        <Avatar
          src={SAMPLE_IMAGE}
          alt="User"
          text="SF"
        />
      </Showcase>
      <Showcase label="text (broken src)">
        <Avatar
          src={BROKEN_IMAGE}
          text="SF"
          color="primary"
        />
      </Showcase>
      <Showcase label="alt (no text)">
        <Avatar
          src={BROKEN_IMAGE}
          alt="Sofía Fernández"
          color="success"
        />
      </Showcase>
      <Showcase label="default icon">
        <Avatar color="highlight" />
      </Showcase>
      <Showcase label="custom icon">
        <Avatar
          Icon={IconStar}
          color="warning"
        />
      </Showcase>
    </Section>
  ),
};

/**
 * Different Tabler icons can be used as the fallback content via the `Icon`
 * prop. Pair them with semantic colours to convey meaning.
 */
export const CustomIcons: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Section title="Tabler icons">
      <Showcase label="User">
        <Avatar
          Icon={IconUser}
          color="default"
        />
      </Showcase>
      <Showcase label="Star">
        <Avatar
          Icon={IconStar}
          color="warning"
        />
      </Showcase>
      <Showcase label="Heart">
        <Avatar
          Icon={IconHeart}
          color="error"
        />
      </Showcase>
      <Showcase label="Briefcase">
        <Avatar
          Icon={IconBriefcase}
          color="primary"
        />
      </Showcase>
      <Showcase label="Check">
        <Avatar
          Icon={IconCheck}
          color="success"
        />
      </Showcase>
      <Showcase label="Info">
        <Avatar
          Icon={IconInfoCircle}
          color="info"
        />
      </Showcase>
    </Section>
  ),
};

/**
 * Disabled state. Reduces opacity and removes pointer events while keeping the
 * avatar visible.
 */
export const Disabled: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Stack sx={{ gap: 4 }}>
      <Section title="Enabled vs Disabled">
        <Showcase label="Image — enabled">
          <Avatar
            src={SAMPLE_IMAGE}
            alt="User"
          />
        </Showcase>
        <Showcase label="Image — disabled">
          <Avatar
            src={SAMPLE_IMAGE}
            alt="User"
            disabled
          />
        </Showcase>
        <Showcase label="Initials — enabled">
          <Avatar
            text="SF"
            color="primary"
          />
        </Showcase>
        <Showcase label="Initials — disabled">
          <Avatar
            text="SF"
            color="primary"
            disabled
          />
        </Showcase>
        <Showcase label="Icon — enabled">
          <Avatar
            Icon={IconUser}
            color="highlight"
          />
        </Showcase>
        <Showcase label="Icon — disabled">
          <Avatar
            Icon={IconUser}
            color="highlight"
            disabled
          />
        </Showcase>
      </Section>
    </Stack>
  ),
};

/**
 * Loading state. Renders a Skeleton placeholder that matches the configured
 * size and shape variant.
 */
export const Loading: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Stack sx={{ gap: 4 }}>
      {SHAPES.map(variant => (
        <Section
          key={variant}
          title={`${variant.charAt(0).toUpperCase()}${variant.slice(1)}`}
        >
          {SIZES.map(size => (
            <Showcase
              key={`${variant}-${size}`}
              label={size}
            >
              <Avatar
                loading
                size={size}
                variant={variant}
              />
            </Showcase>
          ))}
        </Section>
      ))}
    </Stack>
  ),
};

/**
 * Avatars with an attached badge. Badges automatically downgrade to the `dot`
 * variant for small avatars or when no `badgeContent` is provided.
 */
export const WithBadge: Story = {
  parameters: { controls: { disable: true } },
  render: () => (
    <Stack sx={{ gap: 4 }}>
      <Section title="Dot badge (presence)">
        {SIZES.map(size => (
          <Showcase
            key={`dot-${size}`}
            label={size}
          >
            <Avatar
              src={SAMPLE_IMAGE}
              alt="User"
              size={size}
              withBadge
              badgeProps={{ color: 'success', variant: 'dot' }}
            />
          </Showcase>
        ))}
      </Section>
      <Section title="Number badge (notifications)">
        {SIZES.map(size => (
          <Showcase
            key={`num-${size}`}
            label={size}
          >
            <Avatar
              src={SAMPLE_IMAGE}
              alt="User"
              size={size}
              withBadge
              badgeProps={{ badgeContent: 4, color: 'error' }}
            />
          </Showcase>
        ))}
      </Section>
      <Section title="Overflow & custom icons">
        <Showcase label="99+">
          <Avatar
            text="SF"
            color="primary"
            size="large"
            withBadge
            badgeProps={{ badgeContent: 1000, color: 'error' }}
          />
        </Showcase>
        <Showcase label="Bell">
          <Avatar
            Icon={IconBell}
            color="highlight"
            size="large"
            withBadge
            badgeProps={{ badgeContent: 12, color: 'warning' }}
          />
        </Showcase>
        <Showcase label="Initials">
          <Avatar
            text="AB"
            color="success"
            size="medium"
            withBadge
            badgeProps={{ badgeContent: 3, color: 'primary' }}
          />
        </Showcase>
      </Section>
    </Stack>
  ),
};
