

import { audioService } from './services/audioService';
import { AppState, WheelOption } from './types';

// --- Constants & State ---
const COLORS = [
  '#ef4444', '#f97316', '#eab308', '#22c55e', '#06b6d4', '#3b82f6', '#8b5cf6', '#d946ef', '#f43f5e',
];

const INITIAL_OPTIONS: WheelOption[] = [
  { id: '1', label: 'TEAM 1', color: '#ef4444' },
  { id: '2', label: 'TEAM 2', color: '#f97316' },
  { id: '3', label: 'TEAM 3', color: '#eab308' },
  { id: '4', label: 'TEAM 4', color: '#22c55e' },
  { id: '5', label: 'TEAM 5', color: '#06b6d4' },
  { id: '6', label: 'TEAM 6', color: '#3b82f6' },
];

let state: AppState = {
  options: [...INITIAL_OPTIONS],
  history: [],
  isSpinning: false,
  isMuted: false,
  shouldRemoveWinner: false,
};

// --- SVGs for Icons ---
const ICON_VOLUME_2 = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path></svg>`;
const ICON_VOLUME_X = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><line x1="23" y1="9" x2="17" y2="15"></line><line x1="17" y1="9" x2="23" y2="15"></line></svg>`;
const ICON_TRASH = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2-2h4a2 2 0 0 1 2-2h4a2 2 0 0 1 2-2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>`;

declare global {
  interface Window {
    __APP_INITIALIZED__?: boolean;
  }
}

// --- Main Initialization ---
function initApp() {
  if (window.__APP_INITIALIZED__) return;
  window.__APP_INITIALIZED__ = true;
  
  // --- DOM Elements ---
  const els = {
    wheelGroup: document.getElementById('wheel-group') as unknown as SVGGElement,
    wheelContainer: document.getElementById('wheel-container') as HTMLDivElement,
    wheelGlow: document.getElementById('wheel-glow') as HTMLDivElement,
    statusContainer: document.getElementById('status-container') as HTMLDivElement,
    optionsList: document.getElementById('options-list') as HTMLDivElement,
    itemCount: document.getElementById('item-count') as HTMLSpanElement,
    inputText: document.getElementById('input-text') as HTMLTextAreaElement,
    spinBtn: document.getElementById('spin-btn') as HTMLButtonElement,
    addBtn: document.getElementById('add-btn') as HTMLButtonElement,
    clearBtn: document.getElementById('clear-btn') as HTMLButtonElement,
    shuffleBtn: document.getElementById('shuffle-btn') as HTMLButtonElement,
    soundBtn: document.getElementById('sound-btn') as HTMLButtonElement,
    soundIcon: document.getElementById('sound-icon') as HTMLSpanElement,
    removeWinnerCheck: document.getElementById('remove-winner-check') as HTMLInputElement,
    historyList: document.getElementById('history-list') as HTMLDivElement,
    clearHistoryBtn: document.getElementById('clear-history-btn') as HTMLButtonElement,
    totalWinnerCount: document.getElementById('total-winner-count') as HTMLSpanElement,
  };

  // Verify critical elements exist
  if (!els.optionsList || !els.wheelGroup) {
    console.error("Required DOM elements not found. Check HTML IDs.");
    return;
  }

  // --- Helpers ---
  const generateId = () => Math.random().toString(36).substr(2, 9);

  const getCoordinatesForPercent = (percent: number, radius: number) => {
    const x = Math.cos(2 * Math.PI * percent);
    const y = Math.sin(2 * Math.PI * percent);
    return [x * radius, y * radius];
  };

  // --- Rendering ---
  function renderSoundIcon() {
    if(els.soundIcon) els.soundIcon.innerHTML = state.isMuted ? ICON_VOLUME_X : ICON_VOLUME_2;
    if(els.soundBtn) els.soundBtn.setAttribute('title', state.isMuted ? "Unmute" : "Mute");
  }

  function renderHistory() {
    if(els.totalWinnerCount) {
        els.totalWinnerCount.textContent = state.history.length.toString();
    }

    if (!els.historyList) return;

    if (state.history.length === 0) {
      els.historyList.innerHTML = `<div class="empty-msg">No winners yet</div>`;
      if(els.clearHistoryBtn) els.clearHistoryBtn.classList.add('hidden');
      return;
    }

    if(els.clearHistoryBtn) els.clearHistoryBtn.classList.remove('hidden');
    els.historyList.innerHTML = '';

    // Calculate counts by label
    const winCounts: Record<string, number> = {};
    state.history.forEach(r => {
       const label = r.option.label;
       winCounts[label] = (winCounts[label] || 0) + 1;
    });

    state.history.forEach(record => {
      const label = record.option.label;
      const count = winCounts[label];
      const badgeHtml = count > 1 ? `<span class="win-count-badge">x${count}</span>` : '';

      const item = document.createElement('div');
      item.className = "history-item";
      item.innerHTML = `
        <div class="history-label-group">
          <div class="history-dot" style="background-color: ${record.option.color}"></div>
          <span class="history-label">${label} ${badgeHtml}</span>
        </div>
        <span class="history-time">${record.timestamp}</span>
      `;
      els.historyList.appendChild(item);
    });
  }

  function renderList() {
    els.optionsList.innerHTML = '';
    els.itemCount.textContent = `${state.options.length} items`;
    
    if (state.options.length > 0) {
      els.clearBtn.classList.remove('hidden');
      els.shuffleBtn.classList.remove('hidden');
    } else {
      els.clearBtn.classList.add('hidden');
      els.shuffleBtn.classList.add('hidden');
      els.optionsList.innerHTML = `<div class="empty-msg">No options added yet.</div>`;
    }

    state.options.forEach(opt => {
      const item = document.createElement('div');
      item.className = "option-item group";
      item.innerHTML = `
        <div class="option-content">
          <div class="color-dot" style="background-color: ${opt.color}"></div>
          <span class="option-label">${opt.label}</span>
        </div>
        <button class="delete-btn" title="Remove" type="button">
          ${ICON_TRASH}
        </button>
      `;
      
      // Attach delete handler
      const deleteBtn = item.querySelector('.delete-btn');
      deleteBtn?.addEventListener('click', (e) => {
        e.stopPropagation();
        if (state.isSpinning) return;
        state.options = state.options.filter(o => o.id !== opt.id);
        updateUI();
      });

      els.optionsList.appendChild(item);
    });
  }

  function renderWheel() {
    els.wheelGroup.innerHTML = '';
    const count = state.options.length;

    if (count === 0) {
      // Empty wheel placeholder
      const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
      circle.setAttribute("cx", "50");
      circle.setAttribute("cy", "50");
      circle.setAttribute("r", "45");
      circle.setAttribute("fill", "#334155");
      els.wheelGroup.appendChild(circle);
      return;
    }

    const radius = 45;
    const center = 50;

    state.options.forEach((opt, index) => {
      const percent = 1 / count;
      const startAngle = index * percent;
      const endAngle = (index + 1) * percent;

      const [startX, startY] = getCoordinatesForPercent(startAngle, radius);
      const [endX, endY] = getCoordinatesForPercent(endAngle, radius);

      const largeArcFlag = percent > 0.5 ? 1 : 0;

      const pathData = [
        `M ${center} ${center}`,
        `L ${center + startX} ${center + startY}`,
        `A ${radius} ${radius} 0 ${largeArcFlag} 1 ${center + endX} ${center + endY}`,
        'Z',
      ].join(' ');

      const g = document.createElementNS("http://www.w3.org/2000/svg", "g");

      const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
      path.setAttribute("d", pathData);
      path.setAttribute("fill", opt.color);
      path.setAttribute("stroke", "#1e293b");
      path.setAttribute("stroke-width", "0.5");

      // Text
      const midAngle = startAngle + percent / 2;
      const [textX, textY] = getCoordinatesForPercent(midAngle, radius * 0.75);
      
      const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
      text.setAttribute("x", String(center + textX));
      text.setAttribute("y", String(center + textY));
      text.setAttribute("fill", "white");
      text.setAttribute("font-size", "3.5");
      text.setAttribute("font-weight", "bold");
      text.setAttribute("text-anchor", "middle");
      text.setAttribute("dominant-baseline", "middle");
      text.setAttribute("transform", `rotate(${midAngle * 360}, ${center + textX}, ${center + textY}) rotate(0, ${center + textX}, ${center + textY})`);
      text.style.textShadow = '0px 1px 2px rgba(0,0,0,0.5)';
      text.textContent = opt.label.length > 12 ? opt.label.substring(0, 10) + '..' : opt.label;

      g.appendChild(path);
      g.appendChild(text);
      els.wheelGroup.appendChild(g);
    });
  }

  function updateSpinButton() {
    const canSpin = state.options.length >= 2;
    
    // Enable button during spin to allow boost
    els.spinBtn.disabled = !canSpin;
    els.spinBtn.innerHTML = (state.isSpinning ? 'BOOST!' : 'SPIN!') + '<div class="spin-btn-shine"></div>';
    // Enable pointer cursor during spin
    els.wheelContainer.style.cursor = canSpin ? 'pointer' : 'default';
    
    // Status Text
    if (state.isSpinning) {
       els.statusContainer.innerHTML = '<p class="status-text spinning">SPINNING...</p>';
       els.wheelGlow.className = "wheel-glow active";
    } else if (!canSpin) {
       els.statusContainer.innerHTML = '<p class="status-text error">Add at least 2 options to spin!</p>';
       els.wheelGlow.className = "wheel-glow";
    } else {
        if (els.statusContainer.querySelector('.error')) {
            els.statusContainer.innerHTML = '<p class="status-text idle">TAP WHEEL OR SPIN TO START</p>';
        }
    }
  }

  function announceWinner(winner: WheelOption) {
    els.statusContainer.innerHTML = `
      <div class="winner-announcement">
        <p class="winner-label">The Winner Is</p>
        <h2 class="winner-name">${winner.label}</h2>
      </div>
    `;
  }

  function updateUI() {
    renderList();
    renderWheel();
    renderHistory();
    updateSpinButton();
  }

  // --- Logic Class ---
  class WheelController {
    rotation = 0;
    velocity = 0;
    requestRef = 0;
    lastTickIndex = -1;
    lastInteractionTime = Date.now();

    constructor() {
      // Start the permanent animation loop
      this.animate();
    }

    spin() {
      if (state.options.length < 2) return;

      if (state.isSpinning) {
        // Boost velocity when clicked during spin
        this.velocity += 10 + Math.random() * 10;
        // Cap velocity
        if (this.velocity > 60) this.velocity = 60;
        return;
      }
      
      state.isSpinning = true;
      this.lastInteractionTime = Date.now();
      updateSpinButton();
      
      // Initial velocity
      this.velocity = 20 + Math.random() * 15;
    }

    animate() {
      // Calculate rotation changes
      if (state.isSpinning) {
        this.velocity *= 0.985; // Friction
        this.rotation += this.velocity;
      } else {
        // Idle animation: only start after 15 seconds of inactivity
        if (Date.now() - this.lastInteractionTime > 15000) {
            this.rotation += 0.08;
        }
      }
      
      // Update DOM
      if(els.wheelGroup) {
          els.wheelGroup.style.transform = `rotate(${this.rotation}deg)`;
      }

      const count = state.options.length;
      if (count > 0) {
          const sliceAngle = 360 / count;
          
          // Determine current index under pointer (Top/270deg)
          const pointerAngle = 270; 
          const effectiveRotation = this.rotation % 360;
          const rawAngle = pointerAngle - effectiveRotation;
          const positiveAngle = (rawAngle % 360 + 360) % 360;
          const currentIndex = Math.floor(positiveAngle / sliceAngle);

          // Sound (only when actively spinning)
          if (state.isSpinning && this.lastTickIndex !== currentIndex) {
            if (this.lastTickIndex !== -1) {
              audioService.playTick();
            }
            this.lastTickIndex = currentIndex;
          }

          // Stop condition check
          if (state.isSpinning && this.velocity < 0.05) {
            this.stop(currentIndex);
          }
      }
      
      // Always continue the loop
      this.requestRef = requestAnimationFrame(this.animate.bind(this));
    }

    stop(winnerIndex: number) {
      if (!state.isSpinning) return;
      state.isSpinning = false;
      this.lastInteractionTime = Date.now();
      
      const winner = state.options[winnerIndex];
      if (winner) {
        announceWinner(winner);
        audioService.playWin();
        this.fireConfetti();
        
        // Add to history with timestamp
        const now = new Date();
        const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
        
        state.history.unshift({
          option: winner,
          timestamp: timeString
        });
        
        renderHistory();

        // Auto remove winner if enabled
        if (state.shouldRemoveWinner) {
            setTimeout(() => {
                state.options = state.options.filter(o => o.id !== winner.id);
                updateUI();
            }, 1000);
        }
      }
      updateSpinButton();
    }

    fireConfetti() {
      if (window.confetti) {
        const duration = 3000;
        const animationEnd = Date.now() + duration;
        const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 50 };
        const randomInRange = (min: number, max: number) => Math.random() * (max - min) + min;

        const interval: any = setInterval(function() {
          const timeLeft = animationEnd - Date.now();
          if (timeLeft <= 0) return clearInterval(interval);
          const particleCount = 50 * (timeLeft / duration);
          window.confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } });
          window.confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } });
        }, 250);
      }
    }
  }

  const wheelController = new WheelController();

  // --- Event Listeners ---
  els.spinBtn.addEventListener('click', () => wheelController.spin());
  els.wheelContainer.addEventListener('click', () => wheelController.spin());

  els.addBtn.addEventListener('click', () => {
    const val = els.inputText.value;
    if (!val.trim()) return;

    const lines = val.split('\n').map(l => l.trim()).filter(l => l.length > 0);
    if (lines.length === 0) return;

    const newOptions = lines.map((label, index) => ({
      id: generateId(),
      label,
      color: COLORS[(state.options.length + index) % COLORS.length]
    }));

    state.options = [...state.options, ...newOptions];
    els.inputText.value = '';
    
    // Clear winner text if new items added
    if (!state.isSpinning) {
       els.statusContainer.innerHTML = '<p class="status-text idle">TAP WHEEL OR SPIN TO START</p>';
    }
    
    updateUI();
  });

  els.clearBtn.addEventListener('click', () => {
    if (state.isSpinning) return;
    state.options = [];
    els.statusContainer.innerHTML = '<p class="status-text error">Add options to start!</p>';
    updateUI();
  });

  els.shuffleBtn.addEventListener('click', () => {
    if (state.isSpinning || state.options.length < 2) return;
    
    // Fisher-Yates Shuffle using temporary variable for compatibility
    for (let i = state.options.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        const temp = state.options[i];
        state.options[i] = state.options[j];
        state.options[j] = temp;
    }

    updateUI();
  });

  if (els.clearHistoryBtn) {
    els.clearHistoryBtn.addEventListener('click', () => {
      state.history = [];
      renderHistory();
    });
  }

  if (els.soundBtn) {
    els.soundBtn.addEventListener('click', () => {
      state.isMuted = !state.isMuted;
      audioService.toggleMute(state.isMuted);
      renderSoundIcon();
    });
  }

  if (els.removeWinnerCheck) {
    els.removeWinnerCheck.addEventListener('change', (e) => {
      const target = e.target as HTMLInputElement;
      state.shouldRemoveWinner = target.checked;
    });
  }

  // --- Initial Render ---
  updateUI();
  renderSoundIcon();

}

// Use readyState check for robust loading
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initApp);
} else {
    initApp();
}