'use client';

import { shuffle } from 'lodash-es';
import React, { useEffect, useState } from 'react';

import { useChatMessagesStore } from '../../stores';
import { loadingTexts } from '../../useChatMessageActions';

type AnimationState = 0 | 1 | 2 | 3;

// interface AnimationStateConfig {
//   label: string;
//   icon: 'piano' | 'drums' | 'lyrics' | 'waveform';
// }

// const states: Record<AnimationState, AnimationStateConfig> = {
//   0: { label: 'Crafting melodies…', icon: 'piano' },
//   1: { label: 'Drumming up right now…', icon: 'drums' },
//   2: { label: 'Crafting lyrics…', icon: 'lyrics' },
//   3: { label: 'Harmonizing…', icon: 'waveform' },
// };

const PianoIcon: React.FC<{ activeKeys: number[] }> = ({ activeKeys }) => (
  <svg width='32' height='32' viewBox='0 0 32 32' fill='none'>
    <g transform='translate(4, 4)'>
      <rect
        x='4'
        y='4'
        width='4'
        height='16'
        rx='1'
        fill={activeKeys.includes(0) ? '#FFFFFF' : '#fd429c'}
        opacity={activeKeys.includes(0) ? 1 : 0.5}
        style={{ transition: 'all 0.15s ease' }}
      />
      <rect
        x='10'
        y='4'
        width='4'
        height='16'
        rx='1'
        fill={activeKeys.includes(1) ? '#FFFFFF' : '#fd429c'}
        opacity={activeKeys.includes(1) ? 1 : 0.5}
        style={{ transition: 'all 0.15s ease' }}
      />
      <rect
        x='16'
        y='4'
        width='4'
        height='16'
        rx='1'
        fill={activeKeys.includes(2) ? '#FFFFFF' : '#fd429c'}
        opacity={activeKeys.includes(2) ? 1 : 0.5}
        style={{ transition: 'all 0.15s ease' }}
      />
    </g>
  </svg>
);

const DrumsIcon: React.FC<{ activePads: number[] }> = ({ activePads }) => (
  <svg width='32' height='32' viewBox='0 0 32 32' fill='none'>
    <g transform='translate(4, 4)'>
      <rect
        x='4'
        y='4'
        width='7'
        height='7'
        rx='1'
        fill={activePads.includes(0) ? '#FFFFFF' : '#fd429c'}
        opacity={activePads.includes(0) ? 1 : 0.5}
        style={{ transition: 'all 0.15s ease-out' }}
      />
      <rect
        x='13'
        y='4'
        width='7'
        height='7'
        rx='1'
        fill={activePads.includes(1) ? '#FFFFFF' : '#fd429c'}
        opacity={activePads.includes(1) ? 1 : 0.5}
        style={{ transition: 'all 0.15s ease-out' }}
      />
      <rect
        x='4'
        y='13'
        width='7'
        height='7'
        rx='1'
        fill={activePads.includes(2) ? '#FFFFFF' : '#fd429c'}
        opacity={activePads.includes(2) ? 1 : 0.5}
        style={{ transition: 'all 0.15s ease-out' }}
      />
      <rect
        x='13'
        y='13'
        width='7'
        height='7'
        rx='1'
        fill={activePads.includes(3) ? '#FFFFFF' : '#fd429c'}
        opacity={activePads.includes(3) ? 1 : 0.5}
        style={{ transition: 'all 0.15s ease-out' }}
      />
    </g>
  </svg>
);

const LyricsIcon: React.FC<{ activeLines: number[]; starScale: number }> = ({
  activeLines,
  starScale,
}) => (
  <svg width='32' height='32' viewBox='0 0 32 32' fill='none'>
    <g transform='translate(4, 4)'>
      <path
        d='M3 6C3 5.44772 3.44772 5 4 5H13C13.5523 5 14 5.44772 14 6C14 6.55228 13.5523 7 13 7H4C3.44771 7 3 6.55228 3 6Z'
        fill={activeLines.includes(0) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(0) ? 1 : 0.5}
        style={{ transition: 'all 0.2s ease' }}
      />
      <path
        d='M3 10C3 9.44772 3.44772 9 4 9H10C10.5523 9 11 9.44772 11 10C11 10.5523 10.5523 11 10 11H4C3.44772 11 3 10.5523 3 10Z'
        fill={activeLines.includes(1) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(1) ? 1 : 0.5}
        style={{ transition: 'all 0.2s ease' }}
      />
      <path
        d='M4 13C3.44772 13 3 13.4477 3 14C3 14.5523 3.44771 15 4 15H13C13.5523 15 14 14.5523 14 14C14 13.4477 13.5523 13 13 13H4Z'
        fill={activeLines.includes(2) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(2) ? 1 : 0.5}
        style={{ transition: 'all 0.2s ease' }}
      />
      <path
        d='M3 18C3 17.4477 3.44772 17 4 17H18C18.5523 17 19 17.4477 19 18C19 18.5523 18.5523 19 18 19H4C3.44772 19 3 18.5523 3 18Z'
        fill={activeLines.includes(3) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(3) ? 1 : 0.5}
        style={{ transition: 'all 0.2s ease' }}
      />
      <g
        transform={`translate(18, 10) scale(${starScale}) translate(-18, -10)`}
        style={{ transition: 'transform 0.4s ease' }}
      >
        <path
          d='M18.3517 5.95044C18.2309 5.62396 17.7691 5.62396 17.6483 5.95044L16.7094 8.48783C16.6714 8.59048 16.5905 8.6714 16.4878 8.70939L13.9504 9.64831C13.624 9.76911 13.624 10.2309 13.9504 10.3517L16.4878 11.2906C16.5905 11.3286 16.6714 11.4095 16.7094 11.5122L17.6483 14.0496C17.7691 14.376 18.2309 14.376 18.3517 14.0496L19.2906 11.5122C19.3286 11.4095 19.4095 11.3286 19.5122 11.2906L22.0496 10.3517C22.376 10.2309 22.376 9.76911 22.0496 9.64831L19.5122 8.70939C19.4095 8.6714 19.3286 8.59048 19.2906 8.48783L18.3517 5.95044Z'
          fill='#FFFFFF'
          opacity={0.9}
        />
      </g>
    </g>
  </svg>
);

const WaveformIcon: React.FC<{
  barHeights: number[];
  activeLines: number[];
}> = ({ barHeights, activeLines }) => (
  <svg width='32' height='32' viewBox='0 0 32 32' fill='none'>
    <g transform='translate(4, 4)'>
      <rect
        x='3'
        y={12 - barHeights[0] / 2}
        width='2'
        height={barHeights[0]}
        rx='1'
        fill={activeLines.includes(0) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(0) ? 1 : 0.5}
        style={{ transition: 'all 0.05s ease' }}
      />
      <rect
        x='7'
        y={12 - barHeights[1] / 2}
        width='2'
        height={barHeights[1]}
        rx='1'
        fill={activeLines.includes(1) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(1) ? 1 : 0.5}
        style={{ transition: 'all 0.05s ease' }}
      />
      <rect
        x='11'
        y={12 - barHeights[2] / 2}
        width='2'
        height={barHeights[2]}
        rx='1'
        fill={activeLines.includes(2) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(2) ? 1 : 0.5}
        style={{ transition: 'all 0.05s ease' }}
      />
      <rect
        x='15'
        y={12 - barHeights[3] / 2}
        width='2'
        height={barHeights[3]}
        rx='1'
        fill={activeLines.includes(3) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(3) ? 1 : 0.5}
        style={{ transition: 'all 0.05s ease' }}
      />
      <rect
        x='19'
        y={12 - barHeights[4] / 2}
        width='2'
        height={barHeights[4]}
        rx='1'
        fill={activeLines.includes(4) ? '#FFFFFF' : '#fd429c'}
        opacity={activeLines.includes(4) ? 1 : 0.5}
        style={{ transition: 'all 0.05s ease' }}
      />
    </g>
  </svg>
);

export const IncomingMessageLoading: React.FC = () => {
  const [state, setState] = useState<AnimationState>(0);
  const [activeKeys, setActiveKeys] = useState<number[]>([0]);
  const [activePads, setActivePads] = useState<number[]>([0]);
  const [activeLines, setActiveLines] = useState<number[]>([0]);
  const [starScale, setStarScale] = useState(1);
  const [barHeights, setBarHeights] = useState([8, 15, 15, 15, 8]);
  const [randomLoadingTexts] = useState(shuffle(loadingTexts).slice(0, 5));
  const loadingText = useChatMessagesStore((state) => state.loadingText);

  useEffect(() => {
    let animationFrameId: number;
    let startTime = Date.now();
    let lastStateChange = startTime;
    let pianoIndex = 0;
    let drumsIndex = 0;
    let lyricsIndex = 0;
    let waveformIndex = 0;
    let lastPianoUpdate = startTime;
    let lastDrumsUpdate = startTime;
    let lastLyricsUpdate = startTime;
    let lastStarUpdate = startTime;
    let lastWaveformUpdate = startTime;

    const lyricsPatterns = [
      [0],
      [0, 1],
      [0, 1, 2],
      [0, 1, 2, 3],
      [1, 2, 3],
      [2, 3],
      [3],
    ];
    const waveformPatterns = [
      [0, 2, 4],
      [1, 3],
    ];

    const animate = () => {
      const now = Date.now();

      // State transitions every 1.25 seconds, stopping at state 3
      if (now - lastStateChange >= 1250) {
        setState((prev) => {
          if (prev === 3) return 3;
          lastStateChange = now;
          return (prev + 1) as AnimationState;
        });
      }

      // Get current state synchronously for this frame
      setState((currentState) => {
        // Piano animation (state 0) - every 250ms
        if (currentState === 3 && now - lastPianoUpdate >= 250) {
          setActiveKeys([pianoIndex % 3]);
          pianoIndex++;
          lastPianoUpdate = now;
        }

        // Drums animation (state 1) - every 300ms
        if (currentState === 1 && now - lastDrumsUpdate >= 300) {
          setActivePads([drumsIndex % 4]);
          drumsIndex++;
          lastDrumsUpdate = now;
        }

        // Lyrics lines animation (state 2) - every 300ms
        if (currentState === 2 && now - lastLyricsUpdate >= 300) {
          setActiveLines(lyricsPatterns[lyricsIndex % lyricsPatterns.length]);
          lyricsIndex++;
          lastLyricsUpdate = now;
        }

        // Star scale animation (state 2) - every 400ms
        if (currentState === 2 && now - lastStarUpdate >= 400) {
          setStarScale((prev) => (prev === 1 ? 0.85 : 1));
          lastStarUpdate = now;
        }

        // Waveform animation (state 3) - every frame
        if (currentState === 0 && now - lastWaveformUpdate >= 300) {
          const time = now / 400;
          setBarHeights(
            [0, 1, 2, 3, 4].map((i) => {
              const wave = Math.sin(time + i * 0.8) * 0.5 + 0.5;
              return 6 + wave * 9;
            })
          );
          setActiveLines(
            waveformPatterns[waveformIndex % waveformPatterns.length]
          );
          waveformIndex++;
          lastWaveformUpdate = now;
        }

        return currentState;
      });

      animationFrameId = requestAnimationFrame(animate);
    };

    animationFrameId = requestAnimationFrame(animate);
    return () => cancelAnimationFrame(animationFrameId);
  }, []);

  const currentLoadingText = randomLoadingTexts[state];

  return (
    <div className='flex justify-start'>
      <style>{`@keyframes shimmer-text{0%{background-position:200% 0;}100%{background-position:-200% 0;}}`}</style>
      <div className='flex items-center gap-2'>
        <div
          style={{
            transition: 'opacity 0.3s ease',
            opacity: 1,
          }}
        >
          {state === 3 && <PianoIcon activeKeys={activeKeys} />}
          {state === 1 && <DrumsIcon activePads={activePads} />}
          {state === 2 && (
            <LyricsIcon activeLines={activeLines} starScale={starScale} />
          )}
          {state === 0 && (
            <WaveformIcon barHeights={barHeights} activeLines={activeLines} />
          )}
        </div>
        <span className='[animation:shimmer-text_2s_linear_infinite] bg-gradient-to-r from-[rgba(253,66,156,0.7)] via-white to-[rgba(253,66,156,0.7)] bg-[length:200%_100%] bg-clip-text text-sm font-medium text-transparent'>
          {loadingText ?? currentLoadingText}
        </span>
      </div>
    </div>
  );
};

export default IncomingMessageLoading;
