/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import { useEffect, useMemo, useState } from 'react';
import {
  css,
  ensureIsArray,
  fetchTimeRange,
  getTimeOffset,
  styled,
  t,
  useTheme,
} from '@superset-ui/core';
import { DEFAULT_DATE_PATTERN, Tooltip } from '@superset-ui/chart-controls';
import { isEmpty } from 'lodash';
import {
  ColorSchemeEnum,
  PopKPIComparisonSymbolStyleProps,
  PopKPIComparisonValueStyleProps,
  PopKPIProps,
} from './types';
import { useOverflowDetection } from './useOverflowDetection';

const MetricNameText = styled.div<{ metricNameFontSize?: number }>`
  ${({ theme, metricNameFontSize }) => `
    font-family: ${theme.typography.families.sansSerif};
    font-weight: ${theme.typography.weights.normal};
    font-size: ${metricNameFontSize || theme.typography.sizes.s * 2}px;
    text-align: center;
    margin-bottom: ${theme.gridUnit * 3}px;
  `}
`;

const NumbersContainer = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: auto;
  padding: 12px;
`;

const ComparisonValue = styled.div<PopKPIComparisonValueStyleProps>`
  ${({ theme, subheaderFontSize }) => `
    font-weight: ${theme.typography.weights.light};
    display: flex;
    justify-content: center;
    font-size: ${subheaderFontSize || 20}px;
    flex: 1 1 0px;
  `}
`;

const SymbolWrapper = styled.span<PopKPIComparisonSymbolStyleProps>`
  ${({ theme, backgroundColor, textColor }) => `
    background-color: ${backgroundColor};
    color: ${textColor};
    padding: ${theme.gridUnit}px ${theme.gridUnit * 2}px;
    border-radius: ${theme.gridUnit * 2}px;
    margin-right: ${theme.gridUnit}px;
  `}
`;

export default function PopKPI(props: PopKPIProps) {
  const {
    height,
    width,
    bigNumber,
    prevNumber,
    valueDifference,
    percentDifferenceFormattedString,
    metricName,
    metricNameFontSize,
    headerFontSize,
    subheaderFontSize,
    comparisonColorEnabled,
    comparisonColorScheme,
    percentDifferenceNumber,
    currentTimeRangeFilter,
    startDateOffset,
    shift,
    subtitle,
    subtitleFontSize,
    dashboardTimeRange,
    showMetricName,
  } = props;
  const [comparisonRange, setComparisonRange] = useState<string>('');

  useEffect(() => {
    if (!currentTimeRangeFilter || (!shift && !startDateOffset)) {
      setComparisonRange('');
    } else if (!isEmpty(shift) || startDateOffset) {
      const promise: any = fetchTimeRange(
        dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
        currentTimeRangeFilter.subject,
      );
      Promise.resolve(promise).then((res: any) => {
        const dates = res?.value?.match(DEFAULT_DATE_PATTERN);
        const [parsedStartDate, parsedEndDate] = dates ?? [];
        const newShift = getTimeOffset({
          timeRangeFilter: {
            ...currentTimeRangeFilter,
            comparator: `${parsedStartDate} : ${parsedEndDate}`,
          },
          shifts: ensureIsArray(shift),
          startDate: startDateOffset || '',
        });
        fetchTimeRange(
          dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
          currentTimeRangeFilter.subject,
          ensureIsArray(newShift),
        ).then(res => {
          const response: string[] = ensureIsArray(res.value);
          const firstRange: string = response.flat()[0];
          const rangeText = firstRange.split('vs\n');
          setComparisonRange(
            rangeText.length > 1 ? rangeText[1].trim() : rangeText[0],
          );
        });
      });
    }
  }, [currentTimeRangeFilter, shift, startDateOffset, dashboardTimeRange]);

  const theme = useTheme();
  const flexGap = theme.gridUnit * 5;
  const wrapperDivStyles = css`
    font-family: ${theme.typography.families.sansSerif};
    display: flex;
    justify-content: center;
    align-items: center;
    height: ${height}px;
    width: ${width}px;
    overflow: auto;
  `;

  const bigValueContainerStyles = css`
    font-size: ${headerFontSize || 60}px;
    font-weight: ${theme.typography.weights.normal};
    text-align: center;
    margin-bottom: ${theme.gridUnit * 4}px;
  `;

  const SubtitleText = styled.div`
    ${({ theme }) => `
    font-family: ${theme.typography.families.sansSerif};
    font-weight: ${theme.typography.weights.medium};
    text-align: center;
    margin-top: -10px;
    margin-bottom: ${theme.gridUnit * 4}px;
  `}
  `;

  const getArrowIndicatorColor = () => {
    if (!comparisonColorEnabled || percentDifferenceNumber === 0) {
      return theme.colors.grayscale.base;
    }

    if (percentDifferenceNumber > 0) {
      // Positive difference
      return comparisonColorScheme === ColorSchemeEnum.Green
        ? theme.colors.success.base
        : theme.colors.error.base;
    }
    // Negative difference
    return comparisonColorScheme === ColorSchemeEnum.Red
      ? theme.colors.success.base
      : theme.colors.error.base;
  };

  const arrowIndicatorStyle = css`
    color: ${getArrowIndicatorColor()};
    margin-left: ${theme.gridUnit}px;
  `;

  const defaultBackgroundColor = theme.colors.grayscale.light4;
  const defaultTextColor = theme.colors.grayscale.base;
  const { backgroundColor, textColor } = useMemo(() => {
    let bgColor = defaultBackgroundColor;
    let txtColor = defaultTextColor;
    if (comparisonColorEnabled && percentDifferenceNumber !== 0) {
      const useSuccess =
        (percentDifferenceNumber > 0 &&
          comparisonColorScheme === ColorSchemeEnum.Green) ||
        (percentDifferenceNumber < 0 &&
          comparisonColorScheme === ColorSchemeEnum.Red);

      // Set background and text colors based on the conditions
      bgColor = useSuccess
        ? theme.colors.success.light2
        : theme.colors.error.light2;
      txtColor = useSuccess
        ? theme.colors.success.base
        : theme.colors.error.base;
    }

    return {
      backgroundColor: bgColor,
      textColor: txtColor,
    };
  }, [
    theme,
    comparisonColorScheme,
    comparisonColorEnabled,
    percentDifferenceNumber,
  ]);

  const SYMBOLS_WITH_VALUES = useMemo(
    () =>
      [
        {
          defaultSymbol: '#',
          value: prevNumber,
          tooltipText: t('Data for %s', comparisonRange || 'previous range'),
          columnKey: 'Previous value',
        },
        {
          defaultSymbol: '△',
          value: valueDifference,
          tooltipText: t('Value difference between the time periods'),
          columnKey: 'Delta',
        },
        {
          defaultSymbol: '%',
          value: percentDifferenceFormattedString,
          tooltipText: t('Percentage difference between the time periods'),
          columnKey: 'Percent change',
        },
      ].map(item => {
        const config = props.columnConfig?.[item.columnKey];
        return {
          ...item,
          symbol: config?.displayTypeIcon === false ? '' : item.defaultSymbol,
          label: config?.customColumnName || item.columnKey,
        };
      }),
    [
      comparisonRange,
      prevNumber,
      valueDifference,
      percentDifferenceFormattedString,
      props.columnConfig,
    ],
  );

  const visibleSymbols = SYMBOLS_WITH_VALUES.filter(
    symbol => props.columnConfig?.[symbol.columnKey]?.visible !== false,
  );

  const { isOverflowing, symbolContainerRef, wrapperRef } =
    useOverflowDetection(flexGap);

  return (
    <div css={wrapperDivStyles} ref={wrapperRef}>
      <NumbersContainer
        css={
          isOverflowing &&
          css`
            width: fit-content;
            margin: auto;
            align-items: flex-start;
            overflow: auto;
          `
        }
      >
        {showMetricName && metricName && (
          <MetricNameText metricNameFontSize={metricNameFontSize}>
            {metricName}
          </MetricNameText>
        )}

        <div css={bigValueContainerStyles}>
          {bigNumber}
          {percentDifferenceNumber !== 0 && (
            <span css={arrowIndicatorStyle}>
              {percentDifferenceNumber > 0 ? '↑' : '↓'}
            </span>
          )}
        </div>
        {subtitle && (
          <SubtitleText
            style={{
              fontSize: `${subtitleFontSize * height * 0.4}px`,
            }}
          >
            {subtitle}
          </SubtitleText>
        )}

        {visibleSymbols.length > 0 && (
          <div
            css={[
              css`
                display: flex;
                justify-content: space-around;
                gap: ${flexGap}px;
                min-width: 0;
                flex-shrink: 1;
              `,
              isOverflowing
                ? css`
                    flex-direction: column;
                    align-items: flex-start;
                    width: fit-content;
                  `
                : css`
                    align-items: center;
                    width: 100%;
                  `,
            ]}
            ref={symbolContainerRef}
          >
            {visibleSymbols.map((symbol_with_value, index) => (
              <ComparisonValue
                key={`comparison-symbol-${symbol_with_value.columnKey}`}
                subheaderFontSize={subheaderFontSize}
              >
                <Tooltip
                  id="tooltip"
                  placement="top"
                  title={symbol_with_value.tooltipText}
                >
                  {symbol_with_value.symbol && (
                    <SymbolWrapper
                      backgroundColor={
                        index > 0 ? backgroundColor : defaultBackgroundColor
                      }
                      textColor={index > 0 ? textColor : defaultTextColor}
                    >
                      {symbol_with_value.symbol}
                    </SymbolWrapper>
                  )}
                  {symbol_with_value.value}{' '}
                  {props.columnConfig?.[symbol_with_value.columnKey]
                    ?.customColumnName || ''}
                </Tooltip>
              </ComparisonValue>
            ))}
          </div>
        )}
      </NumbersContainer>
    </div>
  );
}
