import { Typography, Box, Grid, useTheme } from '@mui/material';
import { useCreation, useMemoizedFn } from 'ahooks';
import styled from '@emotion/styled';
import isArray from 'lodash/isArray';
import { Icon as IconifyIcon } from '@iconify/react';
import infoCircleIcon from '@iconify-icons/tabler/info-circle';
import LinkIcon from '@arcblock/icons/lib/Link';
import PhoneIcon from '@arcblock/icons/lib/Phone';
import LocationIcon from '@arcblock/icons/lib/Location';
import EmailIcon from '@arcblock/icons/lib/Email';
import TimezoneIcon from '@arcblock/icons/lib/Timezone';
import { withoutProtocol } from 'ufo';
import { useMemo, useCallback } from 'react';

import { User } from '../types';
import Clock from './clock';

const IconMap = {
  timezone: TimezoneIcon,
  email: EmailIcon,
  phone: PhoneIcon,
  location: LocationIcon,
  link: LinkIcon,
};

/**
 * 格式化链接显示
 * 对于 http/https 协议只显示域名，其他协议显示完整链接
 */
function formatLinkDisplay(link: string): string {
  return withoutProtocol(link);
}

/**
 * dark mode 下，转换 icon 颜色
 */
function convertIconColor(isDark: boolean) {
  return isDark
    ? {
        filter: 'brightness(0) saturate(100%) invert(1)',
      }
    : {};
}
const iconSize = {
  width: 16,
  height: 16,
};
interface BasicContentProps {
  user: User;
  renderFields?: string[];
}

// 定义渲染项的类型
interface RenderItem {
  field: string;
  value: string | any;
  key: string;
}

function TimeZoneField({ value }: { value: string }) {
  const theme = useTheme();
  const isDark = theme.palette.mode === 'dark';
  return (
    <Box
      className="user-card__timezone-field"
      sx={{
        display: 'flex',
        alignItems: 'center',
        gap: 1,
      }}>
      <TimezoneIcon {...iconSize} style={convertIconColor(isDark)} />
      <Clock value={value} variant="body2" color="grey.800" />
    </Box>
  );
}

function LinkField({ value }: { value: string }) {
  const theme = useTheme();
  const isDark = theme.palette.mode === 'dark';

  return (
    <Box display="flex" alignItems="center" gap={1} className="user-card__link-field">
      <LinkIcon {...iconSize} style={convertIconColor(isDark)} />
      <LineText variant="body2" color="grey.800">
        <Typography
          component="a"
          href={value}
          style={{ textDecoration: 'none', color: 'inherit', fontSize: 'inherit' }}
          target="_blank"
          variant="body2"
          rel="noopener noreferrer"
          sx={{
            color: 'grey.800',
          }}>
          {formatLinkDisplay(value)}
        </Typography>
      </LineText>
    </Box>
  );
}

function BasicField({ field, value, children = null }: { field: string; value: string; children?: React.ReactNode }) {
  const Icon = IconMap[field as keyof typeof IconMap];
  const theme = useTheme();
  const isDark = theme.palette.mode === 'dark';
  const iconColor = convertIconColor(isDark);
  return (
    <Box
      key={field}
      className={`user-card__${field}-field`}
      sx={{
        display: 'flex',
        alignItems: 'center',
        gap: 1,
      }}>
      {Icon ? (
        <Icon {...iconSize} style={iconColor} />
      ) : (
        <IconifyIcon icon={infoCircleIcon} {...iconSize} {...iconColor} />
      )}
      <LineText variant="body2" color="grey.800">
        {children ?? value}
      </LineText>
    </Box>
  );
}

function BasicContent({ user, renderFields = undefined }: BasicContentProps) {
  const fields = useCreation(() => {
    return renderFields ?? ['bio', 'email', 'phone', 'location', 'timezone', 'link'];
  }, [renderFields]);

  const includeBio = useCreation(() => {
    return fields.includes('bio');
  }, [fields]);

  const metadata = useCreation(() => {
    return (
      user.metadata ?? {
        joinedAt: user?.createdAt,
        email: user?.email,
        phone: {
          country: 'cn',
          phoneNumber: user?.phone ?? '',
        },
      }
    );
  }, [user]);

  const address = useCreation(() => {
    return user.address;
  }, [user.address]);

  const getFieldValue = useCallback(
    (field: string) => {
      if (!field) return '';
      switch (field) {
        case 'bio':
          return user.metadata?.bio || '';
        case 'email':
          return metadata.email || user.email || '';
        case 'phone':
          return metadata.phone?.phoneNumber || user.phone || '';
        case 'location':
          return address?.city || metadata.location || '';
        case 'timezone':
          return metadata.timezone || '';
        case 'link':
          return metadata.links?.map((link) => link.url).filter(Boolean) || [];
        default:
          return user[field as keyof User] || '';
      }
    },
    [user, metadata, address]
  );

  // 计算实际可见的字段数量和渲染元素数量
  const { effectiveRenderCount } = useMemo(() => {
    const visible = fields.filter((field) => {
      if (field === 'bio') return false; // bio field is handled separately
      const value = getFieldValue(field);

      if (value === undefined || value === null || value === '') return false;

      if (isArray(value)) {
        return value.length > 0;
      }

      return String(value).trim().length > 0;
    });

    // 计算实际渲染数量
    const renderCount = visible.reduce((count, field) => {
      const value = getFieldValue(field);
      return count + (Array.isArray(value) ? value.filter((item) => item && String(item).trim()).length : 1);
    }, 0);

    return { visibleFields: visible, effectiveRenderCount: renderCount };
  }, [fields, getFieldValue]);

  // 判断是否需要使用两列布局
  const useDoubleColumn = effectiveRenderCount > 4;

  const isValidValue = useMemoizedFn(
    (value: any) => value !== undefined && value !== null && String(value).trim().length > 0
  );

  // 准备要渲染的所有元素项
  const renderItems = useMemo(() => {
    const items: RenderItem[] = [];

    // 遍历有效字段，展开数组字段为单独的渲染项
    fields.forEach((field) => {
      if (field === 'bio') return; // bio field is handled separately
      const value = getFieldValue(field);

      if (!value) return;

      if (isArray(value)) {
        // 数组类型字段，每个有效项生成一个渲染元素
        value.forEach((item, index) => {
          if (isValidValue(item)) {
            items.push({
              field,
              value: item,
              key: `${field}-${index}`,
            });
          }
        });
      } else if (isValidValue(value)) {
        // 非数组类型字段，生成一个渲染元素
        items.push({
          field,
          value,
          key: field,
        });
      }
    });

    return items;
  }, [fields, getFieldValue, isValidValue]);

  if (fields.length === 0) {
    return null;
  }

  const renderItem = (item: RenderItem) => {
    const { field, value, key } = item;

    switch (field) {
      case 'link':
        return <LinkField key={key} value={value as string} />;
      case 'timezone':
        return <TimeZoneField key={key} value={value as string} />;
      case 'email':
        return (
          <BasicField
            field={field}
            value={value as string}
            // eslint-disable-next-line react/no-children-prop
            children={
              <Typography
                component="a"
                href={`mailto:${value}`}
                rel="noopener noreferrer"
                referrerPolicy="no-referrer"
                style={{
                  color: 'inherit',
                  textDecoration: 'none',
                  fontSize: 'inherit',
                }}>
                {value}
              </Typography>
            }
          />
        );
      default:
        return <BasicField key={key} field={field} value={value as string} />;
    }
  };

  return (
    <Box
      className="user-card__basic-content"
      sx={{
        mt: 1,
        display: 'flex',
        flexDirection: 'column',
        gap: 1.5,
      }}>
      {includeBio && user.metadata?.bio && (
        <LineText variant="body2" color="grey.800" className="user-card__bio-field">
          {user.metadata.bio}
        </LineText>
      )}
      {/* 其他字段 */}
      {useDoubleColumn ? (
        <Grid container spacing={0.5}>
          {renderItems.map((item) => (
            <Grid key={item.key} size={6}>
              {renderItem(item)}
            </Grid>
          ))}
        </Grid>
      ) : (
        <Box
          sx={{
            display: 'flex',
            flexDirection: 'column',
            gap: 0.5,
          }}>
          {renderItems.map((item) => renderItem(item))}
        </Box>
      )}
    </Box>
  );
}

export default BasicContent;

const LineText = styled(Typography)`
  flex: 1;
  display: -webkit-box;
  line-height: 1.5;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-word;
`;
