import { LegacyRef, useCallback, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import Icon from 'semantic-ui-react/dist/commonjs/elements/Icon';
import Label from 'semantic-ui-react/dist/commonjs/elements/Label';
import shallow from 'zustand/shallow';
import { PkmImage } from 'common';
import { Moves, PokeInfo } from 'components';
import { Tip } from 'components/Pokestats/elements';
import { RuleContent } from 'components/Rules/elements';
import { BADGE_IMAGES } from 'constants/badges';
import { TYPE_COLOR } from 'constants/colors';
import { TYPE_COUNT } from 'constants/constant';
import { POKEMAP } from 'constants/pokemon';
import type { Type } from 'constants/types';
import {
  selectBoxed,
  selectCaught,
  selectCompletion,
  selectFailed,
  selectFainted,
  selectShiny,
  selectTeam,
} from 'selectors';
import useStore from 'store';
import { ReactComponent as CaughtSVG } from 'assets/svg/caught.svg';
import { ReactComponent as FailedSVG } from 'assets/svg/failed.svg';
import { ReactComponent as FaintedSVG } from 'assets/svg/fainted.svg';
import { ReactComponent as ShinySVG } from 'assets/svg/shiny.svg';
import styles from './Image.module.scss';

const CALC = 140 * Math.PI;

interface ImageProps {
  forwardedRef?: LegacyRef<HTMLDivElement>;
  responsive?: boolean;
}

function Image({ forwardedRef, responsive = false }: ImageProps): JSX.Element {
  const { t } = useTranslation('stats');
  const badges = useStore(useCallback((state) => state.badges, []));
  const rules = useStore(useCallback((state) => state.rules, []));
  const selectedRuleset = useStore(useCallback((state) => state.selectedRuleset, []));
  const games = useStore(useCallback((state) => state.games, []));
  const teamPokemon = useStore(selectTeam);
  const boxedPokemon = useStore(selectBoxed);
  const faintedPokemon = useStore(selectFainted);
  const caughtPokemon = useStore(selectCaught);
  const completion = useStore(selectCompletion);
  const failedPokemon = useStore(selectFailed);
  const shinyPokemon = useStore(selectShiny);
  const selectedGame = useStore(
    useCallback((state) => state.selectedGame, []),
    shallow
  );
  const summary = useStore(
    useCallback(
      (state) => (state?.selectedGame?.value ? state.summary[state?.selectedGame?.value] : null),
      []
    )
  );
  const setDefaultSummary = useStore(useCallback((state) => state.setDefaultSummary, []));

  useEffect(() => {
    if (!!selectedGame && responsive && !summary) {
      setDefaultSummary();
    }
  }, [responsive, selectedGame, setDefaultSummary, summary]);

  const types = useMemo(() => {
    const TEMP = { ...TYPE_COUNT };

    games[selectedGame?.value]?.encounters?.forEach((enc) => {
      const foundPokemon = POKEMAP.get(enc.pokemon);
      if (foundPokemon) {
        TEMP[foundPokemon.type] += 1;
        if (foundPokemon.dualtype) {
          TEMP[foundPokemon.dualtype] += 1;
        }
      }
    });

    return Object.entries(TEMP).map((entry) => {
      return { title: entry[0] as Type, value: entry[1], color: TYPE_COLOR[entry[0] as Type] };
    });
  }, [games, selectedGame]);

  const getStatus = () => {
    switch (summary?.status) {
      case 0:
        return (
          <b style={{ color: '#FBD200' }}>
            {t('ongoing')} <Icon name="refresh" />
          </b>
        );
      case 1:
        return (
          <b style={{ color: 'green' }}>
            {t('complete')} <Icon name="check" />
          </b>
        );
      case 2:
      default:
        return (
          <b style={{ color: 'red' }}>
            {t('Failed')} <Icon name="x" />
          </b>
        );
    }
  };

  return (
    <div className={`${styles.summary} ${responsive ? styles.responsive : ''}`} ref={forwardedRef}>
      <div className={styles.header} data-testid={`image-header-${responsive}`}>
        <span className={styles.headerTitle}>{summary?.title}</span>
        {getStatus()}
        <div className={styles.badges}>
          {!!selectedGame &&
            badges[selectedGame?.value]?.map((badge, index) => {
              const badgeArr = games[selectedGame?.value]?.badge;
              return (
                <img
                  alt={badge.name}
                  className={`${styles.badge} ${
                    Array.isArray(badgeArr) && badgeArr?.includes(index) ? styles.active : ''
                  }`}
                  key={`${badge.name}-${badge.id}`}
                  src={BADGE_IMAGES[selectedGame?.value][index].src}
                />
              );
            })}
        </div>
      </div>
      <div className={styles.card}>
        <span className={styles.title}>{t('Team')}</span>
        {teamPokemon?.length > 0 ? (
          <div className={styles.team}>
            {teamPokemon?.map((enc) => {
              const foundPokemon = POKEMAP.get(enc.pokemon);
              return (
                <div className={styles.pokemon} key={`team-${enc.id}`}>
                  <div className={styles.image}>
                    <PkmImage name={foundPokemon?.text} shiny={enc?.details?.shiny} />
                  </div>
                  <PokeInfo encounter={enc} pokemon={foundPokemon} />
                  <Moves moves={enc?.details?.moves} />
                </div>
              );
            })}
          </div>
        ) : (
          <Tip missing={t('Team')} />
        )}
      </div>
      <div className={styles.row}>
        {summary?.encounters && (
          <div className={`${styles.card} ${styles.large}`}>
            <span className={styles.title}>{t('encounters')}</span>
            <div className={styles.encounters}>
              <div className={styles.completion}>
                <svg className={styles.circle} width="150" height="150" viewBox="0 0 150 150">
                  <circle className={styles.circlebg} cx={75} cy={75} r="70" strokeWidth="10px" />
                  <circle
                    className={styles.progress}
                    cx={75}
                    cy={75}
                    r="70"
                    strokeWidth="10px"
                    style={{
                      strokeDasharray: CALC,
                      strokeDashoffset: CALC - CALC * completion,
                    }}
                    transform="rotate(-90 75 75)"
                  />
                  <text className={styles.text} x="50%" y="50%" dy=".3em" textAnchor="middle">
                    {completion ? (completion * 100)?.toFixed(0) : 0}%
                  </text>
                </svg>
                <b>{t('completion')}</b>
              </div>
              <div className={styles.byType}>
                <b>{t('all_encounters_by')}</b>
                <div className={styles.byTypeContainer}>
                  {types.map((type) => {
                    return (
                      <div
                        className={styles.type}
                        key={`type-${type.title}`}
                        style={{ backgroundColor: type.color }}
                      >
                        {type.title} {type.value}
                      </div>
                    );
                  })}
                </div>
              </div>
            </div>
          </div>
        )}
        {summary?.stats && (
          <div className={`${styles.card} ${styles.small}`}>
            <span className={styles.title}>{t('stats')}</span>
            <div className={styles.stat}>
              <CaughtSVG className={styles.team} />
              <b>{t('Caught')}</b>
              <Label>{caughtPokemon?.length || 0}</Label>
            </div>
            <div className={styles.stat}>
              <FailedSVG className={styles.team} />
              <b>{t('Failed')}</b>
              <Label>{failedPokemon?.length || 0}</Label>
            </div>
            <div className={styles.stat}>
              <FaintedSVG className={styles.team} />
              <b>{t('Fainted')}</b>
              <Label>{faintedPokemon?.length || 0}</Label>
            </div>
            <div className={styles.stat}>
              <ShinySVG className={styles.team} />
              <b>Shiny</b>
              <Label>{shinyPokemon?.length || 0}</Label>
            </div>
          </div>
        )}
      </div>
      {boxedPokemon?.length > 0 && summary?.boxed && (
        <div className={styles.row}>
          <div className={`${styles.card} ${styles.medium}`}>
            <span className={styles.title}>{t('boxed')}</span>
            <div className={styles.box}>
              {boxedPokemon.map((box, i) => {
                const foundPokemon = POKEMAP.get(box.pokemon);
                return (
                  <div
                    data-testid={`image-box-${i}-${responsive}`}
                    className={styles.pokeImg}
                    key={`boxed-${Number(i) + 1}`}
                  >
                    <PkmImage name={foundPokemon?.text} shiny={box?.details?.shiny} />
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      )}
      {faintedPokemon?.length > 0 && summary?.fainted && (
        <div className={styles.row}>
          <div className={`${styles.card} ${styles.medium}`}>
            <span className={styles.title}>{t('Fainted')}</span>
            <div className={styles.box}>
              {faintedPokemon.map((faint, i) => {
                const foundPokemon = POKEMAP.get(faint.pokemon);
                return (
                  <div
                    data-testid={`image-fainted-${i}-${responsive}`}
                    className={styles.pokeImg}
                    key={`fainted-${Number(i) + 1}`}
                  >
                    <PkmImage name={foundPokemon?.text} shiny={faint?.details?.shiny} />
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      )}
      <div className={styles.row}>
        {summary?.rules && rules[selectedRuleset] && (
          <div className={`${styles.card} ${styles.medium}`}>
            <span className={styles.title}>{t('rules')}</span>
            <div className={styles.rules}>
              {rules[selectedRuleset]?.map((rule, i) => {
                return <RuleContent hideSmart key={`sumrule-${Number(i) + 1}`} i={i} rule={rule} />;
              })}
            </div>
          </div>
        )}
        {summary?.showDescription && (
          <div className={`${styles.card} ${styles.medium}`}>
            <span className={styles.title}>{t('description')}</span>
            <p>{summary?.description || ''}</p>
          </div>
        )}
      </div>
      <span className={styles.credit}>https://nuzlocke.netlify.app</span>
    </div>
  );
}

Image.propTypes = {};

export default Image;