import {
  CharacterClass,
  getLevelFromSPTiered,
  getLevelFromXP,
  getSPForLevelTiered,
  getSkillConstants,
  getXPForLevel,
} from '@rpg-engine/shared';
import React from 'react';
import styled from 'styled-components';
import { uiColors } from '../constants/uiColors';
import { ErrorBoundary } from './Item/Inventory/ErrorBoundary';
import { SpriteFromAtlas } from './shared/SpriteFromAtlas';
import { SimpleProgressBar } from './SimpleProgressBar';
import { Tooltip } from './Tooltip/Tooltip';

export interface ISkillProgressBarProps {
  skillName: string;
  skillKey?: string;
  characterClass?: CharacterClass;
  bgColor: string;
  level: number;
  skillPoints: number;
  texturePath: string;
  showSkillPoints?: boolean;
  skillPointsToNextLevel: number;
  atlasJSON: any;
  atlasIMG: any;
  buffAndDebuff?: number;
}

export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
  bgColor,
  skillName,
  skillKey,
  characterClass,
  // level prop kept in interface for API compatibility, but calculated from skillPoints
  skillPoints: currentSkillPoints,

  texturePath,
  showSkillPoints = true,
  atlasIMG,
  atlasJSON,

  buffAndDebuff,
}) => {
  // Use CharacterClass.None as default if skillKey is provided but characterClass is not
  const effectiveClass = characterClass ?? CharacterClass.None;

  // Calculate the effective level based on actual SP/XP (handles data inconsistencies)
  const calculateEffectiveLevel = (): number => {
    if (!skillKey) {
      // Character level: uses cubic formula (level³ * 3)
      return Math.max(1, getLevelFromXP(currentSkillPoints));
    }

    // Skills: use tiered exponential formula with class-based constants
    const { A, b: baseAffinityB, c } = getSkillConstants(skillKey, effectiveClass);
    const actualLevel = Math.floor(getLevelFromSPTiered(currentSkillPoints, A, baseAffinityB, c));
    return Math.max(1, actualLevel); // Minimum level is always 1 in our system
  };

  const effectiveLevel = calculateEffectiveLevel();

  // Calculate progress based on actual SP/XP position
  const calculateProgress = (): number => {
    // Character level uses cubic XP formula, skills use exponential SP formula
    if (!skillKey) {
      // Character level: uses cubic formula (level³ * 3)
      const actualLevel = Math.max(1, getLevelFromXP(currentSkillPoints));
      const currentLevelXP = getXPForLevel(actualLevel);
      const nextLevelXP = getXPForLevel(actualLevel + 1);

      const range = nextLevelXP - currentLevelXP;
      const progressInLevel = currentSkillPoints - currentLevelXP;

      return Math.min(99.99, Math.max(0, (progressInLevel / Math.max(1, range)) * 100));
    }

    // Skills: use tiered exponential formula with class-based constants
    const { A, b: baseAffinityB, c } = getSkillConstants(skillKey, effectiveClass);

    // Get the actual calculated level (might be 0 for magic)
    const actualLevel = Math.floor(getLevelFromSPTiered(currentSkillPoints, A, baseAffinityB, c));
    const calcLevel = Math.max(c, actualLevel); // Use c as minimum for calculation

    // Calculate SP thresholds based on actual position
    const currentLevelSP = getSPForLevelTiered(calcLevel, A, baseAffinityB, c);
    const nextLevelSP = getSPForLevelTiered(calcLevel + 1, A, baseAffinityB, c);

    // Progress within current level range: (currentSP - currentLevelSP) / (nextLevelSP - currentLevelSP)
    const range = nextLevelSP - currentLevelSP;
    const progressInLevel = currentSkillPoints - currentLevelSP;

    return Math.min(99.99, Math.max(0, (progressInLevel / Math.max(1, range)) * 100));
  };

  const progress = calculateProgress();

  const formatBuffAndDebuff = (value?: number): string =>
    value !== undefined ? value.toFixed(2) : '0';

  const skillsBuffsCalc = (level: number, buffAndDebuff: number): string => {
    if (buffAndDebuff === 0) return '0';
    const result = level * (buffAndDebuff / 100);
    return result > 0 ? `+${result.toFixed(2)}` : `${result.toFixed(2)}`;
  };

  return (
    <>
      <ProgressTitle>
        {buffAndDebuff !== undefined && (
          <>
            {buffAndDebuff > 0 ? (
              <BuffAndDebuffContainer>
                <TitleNameContainer>
                  <TitleNameBuff>{skillName}</TitleNameBuff>
                  <TitleNameBuff>
                    lv {effectiveLevel} ({skillsBuffsCalc(effectiveLevel, buffAndDebuff)})
                  </TitleNameBuff>
                </TitleNameContainer>
                <TitleNameBuffContainer>
                  <TitleNameBuff>
                    (+{formatBuffAndDebuff(buffAndDebuff)}%)
                  </TitleNameBuff>
                </TitleNameBuffContainer>
              </BuffAndDebuffContainer>
            ) : buffAndDebuff < 0 ? (
              <>
                <TitleNameContainer>
                  <TitleNameDebuff>{skillName}</TitleNameDebuff>
                  <TitleNameDebuff>
                    lv {effectiveLevel} ({skillsBuffsCalc(effectiveLevel, buffAndDebuff)})
                  </TitleNameDebuff>
                </TitleNameContainer>
                <div>
                  <TitleNameDebuff>
                    ({formatBuffAndDebuff(buffAndDebuff)}%)
                  </TitleNameDebuff>
                </div>
              </>
            ) : (
              <TitleName>{skillName}</TitleName>
            )}
          </>
        )}
        {!buffAndDebuff && (
          <TitleNameContainer>
            <TitleName>{skillName}</TitleName>
            <ValueDisplay>lv {effectiveLevel}</ValueDisplay>
          </TitleNameContainer>
        )}
      </ProgressTitle>

      <ProgressBody>
        <ProgressIconContainer>
          {atlasIMG && atlasJSON ? (
            <SpriteContainer>
              <ErrorBoundary>
                <SpriteFromAtlas
                  atlasIMG={atlasIMG}
                  atlasJSON={atlasJSON}
                  spriteKey={texturePath}
                  imgScale={1}
                  grayScale
                  opacity={0.5}
                />
              </ErrorBoundary>
            </SpriteContainer>
          ) : (
            <></>
          )}
        </ProgressIconContainer>

        <ProgressBarWrapper>
          <SimpleProgressBar value={progress} bgColor={bgColor} />
          <Tooltip>{skillKey ? 'SP' : 'XP'}: {currentSkillPoints}</Tooltip>
        </ProgressBarWrapper>
      </ProgressBody>
      {showSkillPoints && (
        <SkillDisplayContainer>
          <SkillPointsDisplay>{progress.toFixed(2)}%</SkillPointsDisplay>
        </SkillDisplayContainer>
      )}
    </>
  );
};

const ProgressBarWrapper = styled.div`
  position: relative;

  &:hover ${Tooltip}, &:active ${Tooltip} {
    visibility: visible;
  }
  width: 100%;
  height: auto;
  top: 8px;
`;

const SpriteContainer = styled.div`
  position: relative;
  top: -3px;
  left: 0;
`;

const SkillDisplayContainer = styled.div`
  margin: 0 auto;

  p {
    margin: 0;
  }
`;

const SkillPointsDisplay = styled.p`
  font-size: 0.55rem !important;
  font-weight: bold;
  text-align: center;
`;

const TitleName = styled.span`
  margin-left: 5px;
`;

const TitleNameBuff = styled.span`
  margin-left: 5px;
  color: ${uiColors.lightGreen} !important;
`;

const TitleNameDebuff = styled.span`
  margin-left: 5px;
  color: ${uiColors.red} !important;
`;

const ValueDisplay = styled.span``;

const ProgressIconContainer = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
`;

const ProgressBody = styled.div`
  display: flex;
  flex-direction: row;
  width: 100%;
`;

const ProgressTitle = styled.div`
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  span {
    font-size: 0.6rem;
  }
`;

const BuffAndDebuffContainer = styled.div``;

const TitleNameBuffContainer = styled.div``;

const TitleNameContainer = styled.div`
  display: flex;
  justify-content: space-between;
`;
