import { useEffect, useState } from 'react';
import { getOrCreateEncryptionKey } from './crypto';

const LOCAL_URL = 'http://127.0.0.1:3000';
const HEALTH_URL = `${LOCAL_URL}/api/health`;
const POLL_INTERVAL_MS = 250;

interface Props {
  /** Called once the embedded server responds to a health check. */
  onReady: () => void;
}

/**
 * Shown while the embedded Node.js server (nodejs-mobile) boots in local mode.
 * Starts the engine on mount, then polls /api/health until it responds.
 */
export default function LoadingScreen({ onReady }: Props) {
  const [error, setError] = useState('');

  useEffect(() => {
    let cancelled = false;
    let pollTimer: ReturnType<typeof setTimeout>;

    function pollHealth() {
      fetch(HEALTH_URL)
        .then(res => {
          if (!cancelled && res.ok) {
            onReady();
          } else if (!cancelled) {
            pollTimer = setTimeout(pollHealth, POLL_INTERVAL_MS);
          }
        })
        .catch(() => {
          if (!cancelled) pollTimer = setTimeout(pollHealth, POLL_INTERVAL_MS);
        });
    }

    const nodejs = window.nodejs;
    if (!nodejs) {
      setError('Local server engine is unavailable on this platform.');
      return;
    }

    nodejs.start('main.js', err => {
      if (err && !cancelled) {
        setError('Failed to start local server: ' + String(err));
        return;
      }
      if (cancelled) return;

      // Hand the device-bound encryption key to the embedded Node process over
      // the nodejs-mobile-cordova channel. main.js waits for this message
      // before requiring server.js, so encryption is configured from the
      // first request. The listener is registered synchronously to avoid
      // missing main.js's 'ready' message; the key itself is fetched async.
      nodejs.channel.on('message', msg => {
        if (cancelled || (msg as { type?: string })?.type !== 'ready') return;
        getOrCreateEncryptionKey().then(key => {
          if (!cancelled) nodejs.channel.post('message', { type: 'encryptionKey', key });
        });
      });

      pollHealth();
    });

    return () => {
      cancelled = true;
      clearTimeout(pollTimer);
    };
  }, [onReady]);

  return (
    <div className="setup-root">
      <div className="setup-card" style={{ alignItems: 'center', textAlign: 'center' }}>
        {error ? (
          <>
            <h1 className="setup-title">Couldn't start local server</h1>
            <p className="setup-subtitle">{error}</p>
          </>
        ) : (
          <>
            <div className="spinner" />
            <p className="setup-subtitle">Starting Bill Tracker…</p>
          </>
        )}
      </div>
    </div>
  );
}
