import { useEffect, useRef, useState, type CSSProperties } from 'react';
import frameImage from '../technoborder.png';
import { SOUND_IDS, safeEmit, safePlaySound, safeStopSound } from './hostBridge';
import type { GlitchComponentProps } from './types';

type Screen = 'splash' | 'controls' | 'processing' | 'result';
type ProcessingLine = {
  label: string;
  value: string;
};
type TransitionState = '' | 'crt-collapse' | 'crt-expand';
type VisualClass =
  | 'paradox-point'
  | 'stable-chunk'
  | 'paradox-chunk'
  | 'non-standard-particle-point'
  | 'non-standard-particle-chunk'
  | 'standard-particle-point'
  | 'standard-particle-chunk';
type OutcomeTone = 'stable' | 'warning' | 'paradox' | 'uncertain';

type ToggleState = {
  continuousUniverse: boolean;
  infinitePrecision: boolean;
  chunkParticles: boolean;
};

type OutcomeDefinition = {
  outcome: string;
  description: string;
  intermediate: string;
  visualClass: VisualClass;
  tone: OutcomeTone;
};

const DEFAULT_STATE: ToggleState = {
  continuousUniverse: true,
  infinitePrecision: true,
  chunkParticles: false
};

const OUTCOMES: Record<string, OutcomeDefinition> = {
  '000': {
    outcome: 'Paradoxical',
    intermediate: 'Very very much information.',
    description: 'Space is supposed to be discrete, but each cell must contain ar arbitrary amount of information.',
    visualClass: 'paradox-point',
    tone: 'paradox'
  },
  '001': {
    outcome: 'Digital Physics',
    intermediate: 'Instruction programs remain finite.',
    description: 'Stable but requires continuous rotational symmetry to be emergent',
    visualClass: 'stable-chunk',
    tone: 'stable'
  },
  '010': {
    outcome: '#1 Memory Paradox',
    intermediate: 'Move sets can scale to infinite length',
    description: 'Infinte memory per cell',
    visualClass: 'paradox-point',
    tone: 'paradox'
  },
  '011': {
    outcome: '#2 Memory Paradox',
    intermediate: 'Move sets can scale to infinite length',
    description: 'Chunky particles must grow without bound to hold infinite move set',
    visualClass: 'paradox-chunk',
    tone: 'paradox'
  },
  '100': {
    outcome: 'Paradoxical',
    intermediate: 'Chunky geometry implies discrete space',
    description: 'A continuous universe with chunky particles spanning fundamental cells is a constadiction.',
    visualClass: 'non-standard-particle-point',
    tone: 'warning'
  },
  '101': {
    outcome: 'Paradoxical',
    intermediate: 'The geometry breaks isotropy.',
    description: 'Continuous universe plus chunk particles that imply discrete space is a constradiction.',
    visualClass: 'non-standard-particle-chunk',
    tone: 'warning'
  },
  '110': {
    outcome: 'Standard Physics',
    intermediate: 'The model remains isotropic.',
    description: 'Continuous space with infinite precision preserves the canonical picture.',
    visualClass: 'standard-particle-point',
    tone: 'stable'
  },
  '111': {
    outcome: 'Contradictory',
    intermediate: 'Continuous universe cannot be combined with chunk particles.',
    description: 'Chunky cannot be not chunky',
    visualClass: 'standard-particle-chunk',
    tone: 'uncertain'
  }
};

const PROCESSING_LOGS: Record<string, ProcessingLine[]> = {
  "000": [
    { label: "Universe model", value: "Discrete" },
    { label: "Precision model", value: "Finite (Rejects CRS!)" },
    { label: "Requirement", value: "Isotropy is emergent" },
    { label: "Particle mode", value: "Point particle" },
    { label: "Consistency check", value: "Point state exceeds single-cell information budget" },
    { label: "Verdict trace", value: "Single cell must have arbitrary information capacity" }
  ],
  "001": [
    { label: "Universe model", value: "Discrete" },
    { label: "Precision model", value: "Finite (Rejects CRS!)" },
    { label: "Requirement", value: "Isotropy is emergent" },
    { label: "Particle mode", value: "Chunk particle geometry engaged" },
    { label: "Consistency check", value: "State remains compressible under finite instruction length" },
    { label: "Verdict trace", value: "Digital physics interpretation remains internally stable" }
  ],
  "010": [
    { label: "Universe model", value: "Discrete" },
    { label: "Precision model", value: "Infinite (CRS)" },
    { label: "Particle mode", value: "Point particle" },
    { label: "Consistency check", value: "Each lattice cell requires unbounded memory" },
    { label: "Verdict trace", value: "Inconsistent with isotropy" }
  ],
  "011": [
    { label: "Universe model", value: "Discrete" },
    { label: "Precision model", value: "Infinite (CRS)" },
    { label: "Particle mode", value: "Chunk particle" },
    { label: "Consistency check", value: "Particles grow to express information" },
    { label: "Verdict trace", value: "Chunk particles grow to infinite size" }
  ],
  "100": [
    { label: "Universe model", value: "Continuous manifold" },
    { label: "Precision model", value: "Finite (Rejects CRS!)" },
    { label: "Requirement", value: "Isotropy is emergent" },
    { label: "Particle mode", value: "Point particle" },
    { label: "Consistency check", value: "Severely demotivated" },
    { label: "Verdict trace", value: "No explanation for rejecting CRS. Smell detected." }
  ],
  "101": [
    { label: "Universe model", value: "Continuous manifold" },
    { label: "Precision model", value: "Finite (Rejects CRS!)" },
    { label: "Requirement", value: "Isotropy is emergent" },
    { label: "Particle mode", value: "Chunk particle geometry engaged" },
    { label: "Consistency check", value: "Space is quantized but cells infinitely small" },
    { label: "Verdict trace", value: "Non-standard hybrid geometry. Smell detected" }
  ],
  "110": [
    { label: "Universe model", value: "Continuous manifold" },
    { label: "Precision model", value: "Infinite (CRS)" },
    { label: "Particle mode", value: "Point particle" },
    { label: "Consistency check", value: "Canonical isotropic field picture remains intact" },
    { label: "Verdict trace", value: "Standard physics baseline recovered successfully" }
  ],
  "111": [
    { label: "Universe model", value: "Continuous manifold" },
    { label: "Precision model", value: "Infinite (CRS)" },
    { label: "Particle mode", value: "Chunk particle geometry engaged" },
    { label: "Consistency check", value: "Inconsistent." },
    { label: "Verdict trace", value: "Chunk particle cannot be not chunky" }
  ]
};

function coerceBoolean(value: unknown, fallback: boolean) {
  if (typeof value === 'boolean') return value;
  return fallback;
}

function readToggleState(params: Record<string, unknown> | undefined): ToggleState {
  return {
    continuousUniverse: coerceBoolean(params?.continuousUniverse, DEFAULT_STATE.continuousUniverse),
    infinitePrecision: coerceBoolean(params?.infinitePrecision, DEFAULT_STATE.infinitePrecision),
    chunkParticles: coerceBoolean(params?.chunkParticles, DEFAULT_STATE.chunkParticles)
  };
}

function buildStateKey(state: ToggleState) {
  return [
    state.continuousUniverse ? '1' : '0',
    state.infinitePrecision ? '1' : '0',
    state.chunkParticles ? '1' : '0'
  ].join('');
}

function buildAssumptionsText(state: ToggleState) {
  const universe = state.continuousUniverse ? 'Continuous universe' : 'Discrete universe';
  const precision = state.infinitePrecision ? 'Infinite precision' : 'Finite precision';
  const particles = state.chunkParticles ? 'Chunk particles' : 'Point particles';
  return `${universe} + ${precision} + ${particles}`;
}

function getScore(outcome: OutcomeDefinition) {
  if (outcome.tone === 'stable') return 100;
  if (outcome.tone === 'uncertain') return 60;
  if (outcome.tone === 'warning') return 40;
  return 20;
}

function Visualization({ visualClass }: { visualClass: VisualClass }) {
  if (visualClass === 'paradox-point') {
    return (
      <div className="cube-wrapper">
        <div className="cube">
          <div className="face front" />
          <div className="face back" />
          <div className="face right" />
          <div className="face left" />
          <div className="face top" />
          <div className="face bottom" />
          <div className="particle-point" />
        </div>
        <div className="info-arrow">
          <div className="arrow-line" />
          <div className="arrow-head" />
          <span className="infinite-symbol">∞</span>
        </div>
      </div>
    );
  }

  if (visualClass === 'stable-chunk') {
    return (
      <div className="digital-lattice">
        <div className="digital-grid">
          {Array.from({ length: 9 }, (_, index) => (
            <span
              key={index}
              className={`digital-cell digital-cell-${index}${index === 4 ? ' digital-cell-core' : ''}`}
            />
          ))}
        </div>
        <div className="digital-core">
          <span className="digital-core-dot" />
        </div>
        <div className="digital-scan digital-scan-horizontal" />
        <div className="digital-scan digital-scan-vertical" />
        <div className="digital-aura" />
      </div>
    );
  }

  if (visualClass === 'paradox-chunk') {
    return (
      <div className="chaos-wrapper">
        <div className="central-source">
          <div className="face front" />
          <div className="face back" />
          <div className="face right" />
          <div className="face left" />
          <div className="face top" />
          <div className="face bottom" />
        </div>
        {Array.from({ length: 10 }, (_, index) => (
          <div key={index} className={`debris-cube d-${index}`}>
            <div className="face front" />
            <div className="face back" />
            <div className="face right" />
            <div className="face left" />
            <div className="face top" />
            <div className="face bottom" />
          </div>
        ))}
      </div>
    );
  }

  if (visualClass === 'non-standard-particle-point') {
    return (
      <div className="signal-orbit signal-orbit-point">
        <div className="signal-ring" />
        <div className="signal-dot" />
        <div className="signal-axis" />
      </div>
    );
  }

  if (visualClass === 'non-standard-particle-chunk') {
    return (
      <div className="signal-orbit signal-orbit-chunk">
        <div className="signal-ring" />
        <div className="signal-cube" />
        <div className="signal-axis" />
      </div>
    );
  }

  if (visualClass === 'standard-particle-point') {
    return (
      <div className="physics-observatory">
        <div className="physics-grid" />
        <div className="physics-halo physics-halo-outer" />
        <div className="physics-halo physics-halo-inner" />
        <div className="physics-core-shell">
          <div className="physics-core-point" />
        </div>
        <span className="physics-orbit physics-orbit-1" />
        <span className="physics-orbit physics-orbit-2" />
        <span className="physics-orbit physics-orbit-3" />
      </div>
    );
  }

  return (
    <div className="physics-observatory physics-observatory-chunk">
      <div className="physics-grid" />
      <div className="physics-halo physics-halo-outer" />
      <div className="physics-halo physics-halo-inner" />
      <div className="physics-core-shell physics-core-shell-chunk">
        <div className="physics-core-point physics-core-chunk" />
      </div>
      <span className="physics-orbit physics-orbit-1" />
      <span className="physics-orbit physics-orbit-2" />
      <span className="physics-orbit physics-orbit-3" />
      <div className="physics-question-ring">
        <span className="physics-question">?</span>
      </div>
    </div>
  );
}

export default function AssumptionToggle({
  config,
  onComplete,
  onProgress,
  theme,
  className,
  host
}: GlitchComponentProps) {
  const [toggleState, setToggleState] = useState<ToggleState>(() => readToggleState(config.params));
  const [screen, setScreen] = useState<Screen>('splash');
  const [transitionState, setTransitionState] = useState<TransitionState>('');
  const [result, setResult] = useState(() => OUTCOMES[buildStateKey(readToggleState(config.params))]);
  const [processingKey, setProcessingKey] = useState(() => buildStateKey(readToggleState(config.params)));
  const [processingAssumptions, setProcessingAssumptions] = useState(() =>
    buildAssumptionsText(readToggleState(config.params))
  );
  const [completedLines, setCompletedLines] = useState<string[]>([]);
  const [activeLine, setActiveLine] = useState('');
  const timeoutsRef = useRef<number[]>([]);
  const hostRef = useRef(host);
  const onCompleteRef = useRef(onComplete);
  const onProgressRef = useRef(onProgress);

  useEffect(() => {
    setToggleState(readToggleState(config.params));
  }, [config.params]);

  useEffect(() => {
    hostRef.current = host;
    onCompleteRef.current = onComplete;
    onProgressRef.current = onProgress;
  }, [host, onComplete, onProgress]);

  useEffect(() => {
    if (screen !== 'processing') return;

    const lines = PROCESSING_LOGS[processingKey] ?? [];
    let cancelled = false;

    setCompletedLines([]);
    setActiveLine('');

    const typeLine = (lineIndex: number, charIndex: number) => {
      if (cancelled) return;

      if (lineIndex >= lines.length) {
        queueTimeout(() => {
          if (cancelled) return;
          const finalResult = OUTCOMES[processingKey];
          safePlaySound(hostRef.current, SOUND_IDS.computeDone, { state: processingKey });
          runTransition('result', () => {
            onProgressRef.current?.(100);
            safePlaySound(
              hostRef.current,
              finalResult.tone === 'stable' ? SOUND_IDS.verdictStable : SOUND_IDS.verdictAlert,
              { state: processingKey, outcome: finalResult.outcome }
            );
            safeEmit(hostRef.current, 'verdict-ready', {
              state: processingKey,
              outcome: finalResult.outcome,
              tone: finalResult.tone
            });
            onCompleteRef.current({
              success: true,
              score: getScore(finalResult),
              data: {
                assumptions: processingAssumptions,
                state: processingKey,
                outcome: finalResult.outcome,
                intermediate: finalResult.intermediate,
                description: finalResult.description,
                processingTrace: PROCESSING_LOGS[processingKey].map((entry) => `${entry.label}: ${entry.value}`)
              }
            });
          });
        }, 520);
        return;
      }

      const fullLine = `${lines[lineIndex].label}: ${lines[lineIndex].value}`;

      if (charIndex <= fullLine.length) {
        if (charIndex === 0) {
          safePlaySound(hostRef.current, SOUND_IDS.computeStep, { state: processingKey, lineIndex });
        }
        setActiveLine(fullLine.slice(0, charIndex));
        queueTimeout(() => typeLine(lineIndex, charIndex + 1), 24);
        return;
      }

      setCompletedLines((current) => [...current, fullLine]);
      setActiveLine('');
      if (lineIndex === lines.length - 1) {
        safeStopSound(hostRef.current, SOUND_IDS.computeStep, { state: processingKey, lineIndex });
      }
      queueTimeout(() => typeLine(lineIndex + 1, 0), 170);
    };

    queueTimeout(() => typeLine(0, 0), 180);

    return () => {
      cancelled = true;
      safeStopSound(hostRef.current, SOUND_IDS.computeStep, { state: processingKey });
    };
  }, [processingAssumptions, processingKey, screen]);

  useEffect(() => {
    return () => {
      clearQueuedTimeouts();
    };
  }, []);

  function clearQueuedTimeouts() {
    for (const timeout of timeoutsRef.current) {
      window.clearTimeout(timeout);
    }
    timeoutsRef.current = [];
  }

  function queueTimeout(callback: () => void, delay: number) {
    const timeout = window.setTimeout(callback, delay);
    timeoutsRef.current.push(timeout);
  }

  function runTransition(nextScreen: Screen, onSwapped?: () => void) {
    clearQueuedTimeouts();
    setTransitionState('crt-collapse');
    queueTimeout(() => {
      setScreen(nextScreen);
      onSwapped?.();
      setTransitionState('crt-expand');
      queueTimeout(() => {
        setTransitionState('');
      }, 110);
    }, 110);
  }

  function setToggle<K extends keyof ToggleState>(key: K, value: ToggleState[K]) {
    setToggleState(current => ({ ...current, [key]: value }));
    safePlaySound(host, SOUND_IDS.click, { control: key, value });
  }

  function handleUiHover(target: string) {
    safePlaySound(host, SOUND_IDS.hover, { target });
  }

  function handleInitialize() {
    safeEmit(host, 'session-started', { component: config.name, id: config.id });
    onProgress?.(10);
    runTransition('controls');
  }

  function handleSimulate() {
    const nextKey = buildStateKey(toggleState);
    const nextResult = OUTCOMES[nextKey];
    const nextAssumptions = buildAssumptionsText(toggleState);
    setProcessingKey(nextKey);
    setProcessingAssumptions(nextAssumptions);
    setResult(nextResult);
    safePlaySound(host, SOUND_IDS.computeStart, { state: nextKey });
    safeEmit(host, 'processing-started', {
      state: nextKey,
      assumptions: nextAssumptions
    });
    onProgress?.(45);
    runTransition('processing', () => {
      onProgress?.(70);
    });
  }

  function handleBack() {
    clearQueuedTimeouts();
    safeStopSound(host, SOUND_IDS.computeStep, { state: processingKey });
    safeEmit(host, 'returned-to-controls', { state: processingKey });
    onProgress?.(20);
    runTransition('controls');
  }

  const assumptionsText = buildAssumptionsText(toggleState);
  const showParadoxScreen = screen === 'result' && result.visualClass.includes('paradox');
  const rootStyle = {
    '--gc-primary': theme?.primary || '#248a00',
    '--gc-accent': theme?.accent || '#1c6a00',
    '--gc-bg': theme?.bg || '#ffffff',
    '--gc-bg-secondary': theme?.bgSecondary || '#616161',
    '--gc-text': theme?.text || '#0f172a',
    '--gc-text-muted': theme?.textMuted || '#eaffd8',
    '--gc-border': theme?.border || 'rgba(255,255,255,0.12)',
    '--assumption-frame-image': `url(${frameImage})`
  } as CSSProperties;

  return (
    <div className={`gc-assumption-toggle ${className || ''}`.trim()} style={rootStyle}>
      <div className="component-shell">
        <div className="main-wrapper">
          <div className={`crt-screen ${showParadoxScreen ? 'paradox-errors' : ''}`}>
            <div className={`slides-wrapper ${transitionState}`}>
              {screen === 'splash' && (
                <div className="slide slide-splash">
                  <div className="splash-content">
                    <h1>Foundational Assumption Recombinator Tool</h1>
                    <h2>v1.0</h2>
                    <button
                      type="button"
                      className="action-button"
                      onClick={handleInitialize}
                      onMouseEnter={() => handleUiHover('initialize')}
                      onFocus={() => handleUiHover('initialize')}
                    >
                      Initialize
                    </button>
                  </div>
                </div>
              )}

              {screen === 'controls' && (
                <div className="slide slide-controls">
                  <div className="widget-header">
                    <h1>Settings</h1>
                  </div>

                  <div className="switch-group">
                    <div className="switch-item">
                      <input
                        id={`${config.id}-toggle-universe`}
                        className="switch-input"
                        type="checkbox"
                        checked={toggleState.continuousUniverse}
                        onChange={(event) => setToggle('continuousUniverse', event.target.checked)}
                      />
                      <label
                        className="toggle-track"
                        htmlFor={`${config.id}-toggle-universe`}
                        onMouseEnter={() => handleUiHover('toggle-universe')}
                      >
                        <span className="option-left">Discrete Universe</span>
                        <span className="option-right">Continuous Universe</span>
                      </label>
                    </div>

                    <div className="switch-item">
                      <input
                        id={`${config.id}-toggle-precision`}
                        className="switch-input"
                        type="checkbox"
                        checked={toggleState.infinitePrecision}
                        onChange={(event) => setToggle('infinitePrecision', event.target.checked)}
                      />
                      <label
                        className="toggle-track"
                        htmlFor={`${config.id}-toggle-precision`}
                        onMouseEnter={() => handleUiHover('toggle-precision')}
                      >
                        <span className="option-left">Finite Precision</span>
                        <span className="option-right">Infinite Precision</span>
                      </label>
                    </div>

                    <div className="switch-item">
                      <input
                        id={`${config.id}-toggle-particles`}
                        className="switch-input"
                        type="checkbox"
                        checked={toggleState.chunkParticles}
                        onChange={(event) => setToggle('chunkParticles', event.target.checked)}
                      />
                      <label
                        className="toggle-track"
                        htmlFor={`${config.id}-toggle-particles`}
                        onMouseEnter={() => handleUiHover('toggle-particles')}
                      >
                        <span className="option-left">Point Particles</span>
                        <span className="option-right">Chunk Particles</span>
                      </label>
                    </div>
                  </div>

                  <button
                    type="button"
                    className="action-button"
                    onClick={handleSimulate}
                    onMouseEnter={() => handleUiHover('simulate')}
                    onFocus={() => handleUiHover('simulate')}
                  >
                    Simulate
                  </button>
                </div>
              )}

              {screen === 'result' && (
                <div className="slide slide-result">
                  <div className="bottom-container">
                    <div className="visualization-container">
                      <div className={`art-canvas ${result.visualClass}`}>
                        <Visualization visualClass={result.visualClass} />
                      </div>
                    </div>

                    <div className="result-container">
                  
                      <div className="summary-box">
                        <span className={`result-value result-${result.tone}`}>{result.outcome}</span>
                      </div>

                      <div className="summary-box">
                   
                          <div className="intermediate-result">{result.intermediate}</div>
                    </div>
                        <span className="result-description">{result.description}</span>
                      </div>

                    
                  </div>

                  <button
                    type="button"
                    className="action-button secondary"
                    onClick={handleBack}
                    onMouseEnter={() => handleUiHover('back')}
                    onFocus={() => handleUiHover('back')}
                  >
                    Back
                  </button>
                </div>
              )}

              {screen === 'processing' && (
                <div className="slide slide-processing">
                  <div className="processing-shell">
                    <div className="processing-header">
                      <span className="processing-led" />
                      <h2>Computing Assumption Matrix</h2>
                    </div>
                    <div className="processing-subtitle">Applying Constructor Theoretic Constraints</div>
                    <div className="processing-terminal">
                      {completedLines.map((line, index) => (
                        <div key={`${line}-${index}`} className="processing-line">
                          <span className="processing-prompt">&gt;</span>
                          <span>{line}</span>
                        </div>
                      ))}
                      <div className="processing-line processing-line-active">
                        <span className="processing-prompt">&gt;</span>
                        <span>{activeLine}</span>
                        <span className="processing-cursor" />
                      </div>
                    </div>
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
