import type {CSSProperties} from 'react';
import {Fragment, useCallback} from 'react';
import styled from '@emotion/styled';
import classNames from 'classnames';

import {Tooltip} from 'sentry/components/tooltip';
import {IconClock, IconRefresh} from 'sentry/icons';
import {tct} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import getFrameDetails from 'sentry/utils/replays/getFrameDetails';
import useCrumbHandlers from 'sentry/utils/replays/hooks/useCrumbHandlers';
import IconWrapper from 'sentry/views/replays/detail/iconWrapper';
import TraceGrid from 'sentry/views/replays/detail/perfTable/traceGrid';
import type {ReplayTraceRow} from 'sentry/views/replays/detail/perfTable/useReplayPerfData';
import TimestampButton from 'sentry/views/replays/detail/timestampButton';
import type {OnDimensionChange} from 'sentry/views/replays/detail/useVirtualListDimentionChange';

interface Props {
  currentHoverTime: number | undefined;
  currentTime: number;
  index: number;
  onDimensionChange: OnDimensionChange;
  startTimestampMs: number;
  style: CSSProperties;
  traceRow: ReplayTraceRow;
}

export default function PerfRow({
  currentHoverTime,
  currentTime,
  index,
  onDimensionChange,
  startTimestampMs,
  style,
  traceRow,
}: Props) {
  const {lcpFrames, replayFrame: frame, paintFrames, flattenedTraces} = traceRow;
  const {color, description, title, icon} = getFrameDetails(frame);
  const lcp = lcpFrames.length ? getFrameDetails(lcpFrames[0]) : null;

  const handleDimensionChange = useCallback(
    () => onDimensionChange(index),
    [onDimensionChange, index]
  );

  const {onMouseEnter, onMouseLeave, onClickTimestamp} = useCrumbHandlers();

  const handleClickTimestamp = useCallback(
    () => onClickTimestamp(frame),
    [onClickTimestamp, frame]
  );
  const handleMouseEnter = useCallback(() => onMouseEnter(frame), [onMouseEnter, frame]);
  const handleMouseLeave = useCallback(() => onMouseLeave(frame), [onMouseLeave, frame]);

  const hasOccurred = frame ? currentTime >= frame.offsetMs : false;
  const isBeforeHover = frame
    ? currentHoverTime === undefined || currentHoverTime >= frame.offsetMs
    : false;

  return (
    <PerfListItem
      className={classNames({
        beforeCurrentTime: hasOccurred,
        afterCurrentTime: !hasOccurred,
        beforeHoverTime: currentHoverTime !== undefined && isBeforeHover,
        afterHoverTime: currentHoverTime !== undefined && !isBeforeHover,
      })}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
      style={style}
    >
      <Vertical style={{gap: space(1)}}>
        <Horizontal style={{gap: space(1)}}>
          <IconWrapper color={color} hasOccurred={hasOccurred}>
            {icon}
          </IconWrapper>
          <Vertical style={{flexGrow: 1}}>
            <Title hasOccurred={hasOccurred}>{title}</Title>
            <Description title={description} showOnlyOnOverflow>
              {description}
            </Description>
          </Vertical>
          <IconLabel>
            {lcp ? (
              <Fragment>
                <IconClock size="xs" />
                {tct('[lcp] LCP', {lcp: lcp.description})}
              </Fragment>
            ) : null}
          </IconLabel>
          <IconLabel>
            {paintFrames.length ? (
              <Fragment>
                <IconRefresh size="xs" />
                {tct('[count] paint events', {count: paintFrames.length})}
              </Fragment>
            ) : null}
          </IconLabel>
          <TimestampButton
            onClick={handleClickTimestamp}
            startTimestampMs={startTimestampMs}
            timestampMs={frame.timestampMs}
          />
        </Horizontal>
        {flattenedTraces.map((flatTrace, i) => (
          <TraceGrid
            key={i}
            flattenedTrace={flatTrace}
            onDimensionChange={handleDimensionChange}
          />
        ))}
      </Vertical>
    </PerfListItem>
  );
}

const PerfListItem = styled('div')`
  padding: ${space(1)} ${space(1.5)};

  /* Overridden in TabItemContainer, depending on *CurrentTime and *HoverTime classes */
  border-top: 1px solid transparent;
  border-bottom: 1px solid transparent;
`;

const Vertical = styled('div')`
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
`;

const Horizontal = styled('div')`
  display: flex;
  flex: auto 1 1;
  flex-direction: row;

  font-size: ${p => p.theme.fontSizeSmall};
  overflow: auto;
`;

const Title = styled('span')<{hasOccurred?: boolean}>`
  color: ${p => (p.hasOccurred ? p.theme.gray400 : p.theme.gray300)};
  font-size: ${p => p.theme.fontSizeMedium};
  font-weight: bold;
  line-height: ${p => p.theme.text.lineHeightBody};
  text-transform: capitalize;
  ${p => p.theme.overflowEllipsis};
`;

const Description = styled(Tooltip)`
  ${p => p.theme.overflowEllipsis};
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  line-height: ${p => p.theme.text.lineHeightBody};
  color: ${p => p.theme.subText};
`;

const IconLabel = styled('span')`
  display: flex;
  align-items: center;
  align-self: baseline;
  gap: 4px;
`;
