import { Box, Badge, Tooltip, type SvgIconProps } from '@mui/material';
import styled from '@emotion/styled';
import { lazy, Suspense, useCallback, useEffect, useMemo, useState } from 'react';
import { useCreation, useMemoizedFn, useInterval, useUnmount } from 'ahooks';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { translate } from '@arcblock/ux/lib/Locale/util';
import { formatToDatetime } from '@arcblock/ux/lib/Util';
import type { UserMetadata } from '../../../@types';
import { DurationEnum, StatusEnum } from '../../../@types';
import StatusDialog from '../status-dialog';
import { translations } from '../../libs/locales';
import { getTimeRemaining, isNotClear, isWithinTimeRange } from './utils';
import { StatusItem } from '../status-selector/menu-item';

const MeetingIcon = lazy(() => import('@arcblock/icons/lib/Meeting'));
const CommunityIcon = lazy(() => import('@arcblock/icons/lib/Community'));
const HolidayIcon = lazy(() => import('@arcblock/icons/lib/Holiday'));
const OffSickIcon = lazy(() => import('@arcblock/icons/lib/OffSick'));
const WorkingRemotelyIcon = lazy(() => import('@arcblock/icons/lib/WorkingRemotely'));

const StatusIconMap: Record<StatusEnum, React.FC<SvgIconProps> | undefined> = {
  [StatusEnum.Meeting]: MeetingIcon,
  [StatusEnum.Community]: CommunityIcon,
  [StatusEnum.Holiday]: HolidayIcon,
  [StatusEnum.OffSick]: OffSickIcon,
  [StatusEnum.WorkingRemotely]: WorkingRemotelyIcon,
};

const QuickSettings = {
  [StatusEnum.Meeting]: {
    duration: DurationEnum.OneHour,
    durationName: 'userStatus.duration.OneHour',
  },
  [StatusEnum.Community]: {
    duration: DurationEnum.ThirtyMinutes,
    durationName: 'userStatus.duration.ThirtyMinutes',
  },
  [StatusEnum.Holiday]: {
    duration: DurationEnum.ThisWeek,
    durationName: 'userStatus.duration.ThisWeek',
  },
  [StatusEnum.OffSick]: {
    duration: DurationEnum.Today,
    durationName: 'userStatus.duration.Today',
  },
  [StatusEnum.WorkingRemotely]: {
    duration: DurationEnum.ThisWeek,
    durationName: 'userStatus.duration.ThisWeek',
  },
};

export default function UserStatus({
  isMobile = undefined,
  size,
  isMyself,
  status,
  onChange,
  timezone = undefined,
}: {
  isMobile?: boolean;
  size: number;
  isMyself: boolean;
  status: UserMetadata['status'];
  onChange: (v: UserMetadata['status']) => void;
  timezone?: string;
}) {
  const { locale } = useLocaleContext();
  const t = useMemoizedFn((key, data = {}) => {
    return translate(translations, key, locale, 'en', data);
  });

  const [interval, setInterval] = useState<number | undefined>(undefined);

  const pauseInterval = useMemoizedFn(() => {
    setInterval(undefined);
  });

  useEffect(() => {
    setInterval(1000);
  }, [status]);

  const clear = useInterval(() => {
    if (status?.value && status?.dateRange?.length === 2) {
      const notClear = isNotClear(status);
      if (notClear) {
        return;
      }
      const isWithin = isWithinTimeRange(status.dateRange as [Date, Date]);
      if (!isWithin) {
        pauseInterval();
        onChange(undefined);
      } else {
        // 根据距离结束时间长度，设置 interval
        const timeRemaining = getTimeRemaining(status.dateRange[1]);
        if (timeRemaining > 0) {
          setInterval(timeRemaining);
        } else {
          pauseInterval();
          onChange(undefined);
        }
      }
    } else {
      pauseInterval();
    }
  }, interval);

  useUnmount(() => {
    clear();
  });

  const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>(null);

  const getDurationData = useCallback(() => {
    const data = Object.keys(DurationEnum).map((key) => ({
      id: DurationEnum[key as keyof typeof DurationEnum],
      name: t(`userStatus.duration.${key}`),
    }));
    return data;
  }, [t]);

  const statusData = useCreation(() => {
    const durationData = getDurationData();
    return Object.keys(StatusEnum).map((key) => {
      const quickSetting = QuickSettings[StatusEnum[key as keyof typeof StatusEnum]];

      return {
        id: StatusEnum[key as keyof typeof StatusEnum],
        name: t(`userStatus.${key}`),
        icon: StatusIconMap[StatusEnum[key as keyof typeof StatusEnum]],
        ...(quickSetting ? { duration: quickSetting.duration, durationName: t(quickSetting.durationName) } : {}),
        children: durationData,
      };
    });
  }, [t, getDurationData, locale]);

  const onOpenStatusSelector = (event: React.MouseEvent<HTMLDivElement>) => {
    if (!isMyself) {
      return;
    }
    setAnchorEl(event.currentTarget);
  };

  const onCloseStatusSelector = () => {
    setAnchorEl(null);
  };

  const onStatusChange = (v?: UserMetadata['status']) => {
    if (!isMyself) {
      return;
    }
    onChange(v);
    onCloseStatusSelector();
  };

  const StatusIcon = StatusIconMap[status?.value as keyof typeof StatusIconMap];

  const tooltipTitle = useMemo(() => {
    const currentStatus = statusData.find((item) => item.id === status?.value);
    if (currentStatus) {
      const localeOption = locale === 'zh' ? 'zh-cn' : 'en-us';
      let range;
      const notClear = isNotClear(status);
      if (!notClear) {
        range = status?.dateRange?.map((item) => {
          return formatToDatetime(item, { locale: localeOption });
        });
      }
      if (range && range.length > 0) {
        return `${currentStatus.name}: ${range.join('~')}`;
      }
      return currentStatus.name;
    }
    return null;
  }, [status, statusData, locale]);

  const open = Boolean(anchorEl);

  return (
    <StatusDiv size={size} isMobile={isMobile}>
      <Tooltip title={tooltipTitle}>
        <Box
          className="status-icon"
          onClick={onOpenStatusSelector}
          sx={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
          }}>
          {StatusIcon ? (
            <Suspense fallback={null}>
              <StatusIcon style={{ width: 16, height: 16 }} />
            </Suspense>
          ) : (
            <Badge color="success" variant="dot" />
          )}
        </Box>
      </Tooltip>
      {open && (
        <StatusDialog
          selected={status}
          data={statusData as StatusItem[]}
          open={open}
          onSelect={onStatusChange}
          onClose={onCloseStatusSelector}
          timezone={timezone}
        />
      )}
    </StatusDiv>
  );
}

const StatusDiv = styled('div')<{ size: number; isMobile?: boolean }>`
  position: absolute;
  left: ${({ size }) => `${(size * 3) / 4}px`};
  top: ${({ size }) => `${size * 0.65}px`};
  width: ${({ isMobile }) => (isMobile ? '22px' : '32px')};
  height: ${({ isMobile }) => (isMobile ? '22px' : '32px')};
  border-radius: ${({ isMobile }) => (isMobile ? '11px' : '16px')};
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #ffffff;
  overflow: hidden;
  white-space: nowrap;
  cursor: pointer;

  .status-icon {
    flex-shrink: 0;
    width: ${({ isMobile }) => (isMobile ? '16px' : '26px')};
    height: ${({ isMobile }) => (isMobile ? '16px' : '26px')};
    border-radius: ${({ isMobile }) => (isMobile ? '8px' : '13px')};
    background-color: #eff1f5;
  }
`;
