import 'reflect-metadata';
import 'katex/dist/katex.min.css';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './styles/variables.css';
import './index.css';
import App from './App.tsx';
import DialogProvider from './components/common/DialogProvider';
import { KGCore } from './core/KGCore';
import { KGAudioInterface } from './core/audio-interface/KGAudioInterface';
import { ConfigManager } from './core/config/ConfigManager';
import { KGMidiInput } from './core/midi-input/KGMidiInput';
import { KGDebugger } from './core/KGDebugger';
import { enumerateAudioDevices, validateConfiguredAudioDevices } from './util/audioDeviceUtil';

const root = createRoot(document.getElementById('root')!);

// OPFS requires a secure context (HTTPS or localhost). Show a clear error instead of crashing.
if (!window.isSecureContext) {
  root.render(
    <StrictMode>
      <div
        style={{
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          height: '100vh',
          gap: '16px',
          padding: '32px',
          textAlign: 'center',
          color: 'rgba(255,255,255,0.87)',
          background: '#1e1e1e',
          fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
        }}
      >
        <div style={{ fontSize: '48px' }}>🔒</div>
        <h1 style={{ fontSize: '22px', fontWeight: 600, margin: 0 }}>Secure Context Required</h1>
        <p style={{ fontSize: '14px', color: 'rgba(255,255,255,0.55)', maxWidth: '480px', lineHeight: 1.6 }}>
          K.G.Studio uses the browser&apos;s Origin Private File System (OPFS) to store projects,
          which requires a <strong style={{ color: 'rgba(255,255,255,0.8)' }}>secure context</strong>.
        </p>
        <div
          style={{
            background: '#2a2a2a',
            border: '1px solid #444',
            borderRadius: '8px',
            padding: '16px 24px',
            fontSize: '13px',
            lineHeight: 2,
            color: 'rgba(255,255,255,0.7)',
          }}
        >
          <div>Use <code style={{ color: '#7cb8ff' }}>https://</code> instead of <code style={{ color: '#f28b82' }}>http://</code></div>
          <div>or access via <code style={{ color: '#7cb8ff' }}>localhost</code> / <code style={{ color: '#7cb8ff' }}>127.0.0.1</code></div>
        </div>
      </div>
    </StrictMode>,
  );
} else {
// Initialize KGCore instance
await KGCore.instance().initialize();

const configManager = ConfigManager.instance();
try {
  const deviceSnapshot = await enumerateAudioDevices();
  const validatedDevices = validateConfiguredAudioDevices(
    configManager.get('audio.input_device_id') as string | undefined,
    configManager.get('audio.output_device_id') as string | undefined,
    deviceSnapshot
  );

  const updates: Array<Promise<void>> = [];
  const statusMessages: string[] = [];

  if (validatedDevices.inputFellBackToDefault) {
    updates.push(configManager.set('audio.input_device_id', 'default'));
    statusMessages.push('Previously selected audio input device is unavailable; using System Default.');
  }
  if (validatedDevices.outputFellBackToDefault) {
    updates.push(configManager.set('audio.output_device_id', 'default'));
    statusMessages.push('Previously selected audio output device is unavailable; using System Default.');
  }

  if (updates.length > 0) {
    await Promise.all(updates);
    KGCore.instance().setStatus(statusMessages.join(' '));
  }

  await KGAudioInterface.instance().applyConfiguredOutputDevice(validatedDevices.outputDeviceId);
} catch (error) {
  console.warn('Audio device validation skipped:', error);
}

// Initialize KGMidiInput instance
await KGMidiInput.instance().initialize();

// Attach debugger to global window in development mode
if (import.meta.env.DEV) {
  const dbg = KGDebugger.instance();
  (window as unknown as { KGDebugger: KGDebugger; sh: () => Promise<void> }).KGDebugger = dbg;
  (window as unknown as { sh: () => Promise<void> }).sh = () => dbg.startShell();
  console.log('🔧 KGDebugger attached to window - try: KGDebugger.help() or sh()');
}

// Start audio context on first user interaction
let audioContextStarted = false;
const tryStartAudioContext = async () => {
  if (!audioContextStarted) {
    audioContextStarted = true;
    try {
      const audioInterface = KGAudioInterface.instance();
      if (!audioInterface.getIsAudioContextStarted()) {
        await audioInterface.startAudioContext();
        console.log('Audio context started on first user interaction');
      }
    } catch (error) {
      console.log('Audio context start failed:', error);
      audioContextStarted = false; // Allow retry
    }
  }
};

// Request MIDI access on first user interaction
let midiAccessRequested = false;
const tryRequestMIDIAccess = async () => {
  if (!midiAccessRequested) {
    midiAccessRequested = true;
    try {
      const midiInput = KGMidiInput.instance();
      if (!midiInput.getMIDIAccess()) {
        await midiInput.requestMIDIAccess();
        console.log('MIDI access granted on first user interaction');
      }
    } catch (error) {
      console.log('MIDI access failed:', error);
      midiAccessRequested = false; // Allow retry
    }
  }
};

// Combined handler for first user interaction
const handleFirstInteraction = async () => {
  await tryStartAudioContext();
  await tryRequestMIDIAccess();

  // Remove listeners after first attempt
  document.removeEventListener('click', handleFirstInteraction);
  document.removeEventListener('touchstart', handleFirstInteraction);
  document.removeEventListener('keydown', handleFirstInteraction);
};

// Listen for first user interaction
document.addEventListener('click', handleFirstInteraction, { passive: true });
document.addEventListener('touchstart', handleFirstInteraction, { passive: true });
document.addEventListener('keydown', handleFirstInteraction, { passive: true });

// Add event listener for beforeunload event
window.addEventListener('beforeunload', (event) => {
  // Cancel the event
  event.preventDefault();
  // Chrome requires returnValue to be set
  event.returnValue = '';
  
  // The browser will show a standard confirmation dialog
  // with a message like "Changes you made may not be saved."
  // Note: Custom messages are no longer supported in modern browsers for security reasons
});

  root.render(
    <StrictMode>
      <DialogProvider>
        <App />
      </DialogProvider>
    </StrictMode>,
  );
} // end isSecureContext else
