import React, { useState, useEffect, useRef } from 'react';
import { Button } from 'avanza-ui';
import './App.css';
import StudioPortal from './components/Portal/StudioPortal';
import { isAllowedOrigin } from './utils/postMessage';
import { Room } from 'livekit-client';

function App() {
  const [isConnected, setIsConnected] = useState(false);
  const [credentials, setCredentials] = useState({
    serverUrl: import.meta.env.VITE_LIVEKIT_URL || 'ws://localhost:7880',
    token: '',
    roomName: 'Studio Demo',
  });

  const [tempToken, setTempToken] = useState('');
  const autoAttemptRef = useRef(false);
  // external LiveKit Room managed by App when token is received
  const roomRef = useRef<Room | null>(null);
  const messageSourceRef = useRef<Window | null>(null);
  // store the last validated origin that sent a token so we can ACK securely
  const lastValidatedOrigin = useRef<string | null>(null);

  // Called when the LiveKit room reports connected
  const handleRoomConnected = () => {
    setIsConnected(true);
    // send connected ACK to the validated origin if available
    try {
      const payload = { type: 'LIVEKIT_ACK', status: 'connected' };
      const targetOrigin = lastValidatedOrigin.current || '*';
      // Prefer replying directly to the message source window if available
      if (messageSourceRef.current && typeof (messageSourceRef.current as any).postMessage === 'function') {
        try { (messageSourceRef.current as any).postMessage(payload, targetOrigin); } catch (e) { /* ignore */ }
      }
      if (window.opener && !window.opener.closed) {
        try { window.opener.postMessage(payload, targetOrigin); } catch (e) { /* ignore */ }
      }
      if (window.parent && window.parent !== window) {
        try { window.parent.postMessage(payload, targetOrigin); } catch (e) { /* ignore */ }
      }
    } catch (e) { /* ignore */ }
  };

  const handleRoomDisconnected = () => {
    setIsConnected(false);
    try {
      const payload = { type: 'LIVEKIT_ACK', status: 'disconnected' };
      const targetOrigin = lastValidatedOrigin.current || '*';
      if (window.opener && !window.opener.closed) {
        try { window.opener.postMessage(payload, targetOrigin); } catch (e) { /* ignore */ }
      }
      if (window.parent && window.parent !== window) {
        try { window.parent.postMessage(payload, targetOrigin); } catch (e) { /* ignore */ }
      }
    } catch (e) {}
    // disconnect and clear app-managed room
    try { if (roomRef.current) { roomRef.current.disconnect(); roomRef.current = null; } } catch(e){}
  };

  // Cleanup app-managed room on unmount
  useEffect(() => {
    return () => {
      try { if (roomRef.current) { roomRef.current.disconnect(); roomRef.current = null; } } catch(e){}
    };
  }, []);

  // Listen for LIVEKIT_TOKEN posted via postMessage (handshake flow)
  useEffect(() => {
    // central token handler used by both message events and custom events
    const handleIncomingToken = async (payload: any, origin?: string | null, source?: any) => {
      try {
        const originToUse = origin || null;
        if (!isAllowedOrigin(originToUse)) {
          return;
        }
        // store validated origin and message source for ACKs
        if (originToUse) lastValidatedOrigin.current = originToUse;
        if (source) messageSourceRef.current = source;

        if (payload?.url) setCredentials(prev => ({ ...prev, serverUrl: String(payload.url) }));
        const receivedToken = String(payload.token || payload?.token);
        setTempToken(receivedToken);

        // cleanup previous room if exists
        try { if (roomRef.current) { roomRef.current.disconnect(); roomRef.current = null; } } catch(e){}

        const newRoom = new Room();
        roomRef.current = newRoom;
        try {
          const sUrl = payload?.url || credentials.serverUrl;
          await newRoom.connect(sUrl, receivedToken);
          setCredentials(prev => ({ ...prev, token: receivedToken }));
          handleRoomConnected();
        } catch (err) {
          console.error('App-managed room connect failed', err);
        }

        if (!autoAttemptRef.current) {
          autoAttemptRef.current = true;
          setTimeout(() => { if (receivedToken) handleConnectWithToken(receivedToken); }, 60);
        }
      } catch (err) { console.debug('handleIncomingToken error', err); }
    };

    function onMessage(e: MessageEvent) {
      try {
        const d = e.data || {};
        if (d?.type === 'LIVEKIT_TOKEN' && d.token) {
          // call central handler and pass origin/source
          handleIncomingToken(d, e.origin || null, e.source);
        }
      } catch (err) { console.debug('postMessage in App error', err) }
    }
    window.addEventListener('message', onMessage);

    // Also listen for the custom event dispatched by main.tsx
    function onCustomToken(e: any) {
      try {
        const detail = e?.detail || (window as any).__AVANZACAST_PENDING_TOKEN || null;
        // attempt to recover origin/source from globals set by main.tsx if present
        const lastMsg = (window as any).__AVZ_LAST_MSG_SOURCE || null;
        const origin = lastMsg?.origin || null;
        const source = lastMsg?.source || null;
        if (detail && detail.token) handleIncomingToken(detail, origin, source);
      } catch(err) { console.debug('custom token handler error', err); }
    }
    window.addEventListener('avz:livekit:token', onCustomToken as EventListener);

    return () => {
      window.removeEventListener('message', onMessage);
      window.removeEventListener('avz:livekit:token', onCustomToken as EventListener);
    };
  }, []);


  function handleConnectWithToken(tokenVal: string) {
    if (tokenVal && tokenVal.trim()) {
      setCredentials(prev => ({ ...prev, token: tokenVal }));
      setIsConnected(true);
    }
  }

  const handleConnect = () => {
    if (tempToken.trim()) {
      setCredentials(prev => ({ ...prev, token: tempToken }));
      setIsConnected(true);
    }
  };

  // Update a global #status element and notify opener/parent when connected — helps E2E tests detect ACK/state
  useEffect(() => {
    try {
      const setStatus = (txt: string) => {
        try {
          let el = document.getElementById('status');
          if (!el) {
            el = document.createElement('div');
            el.id = 'status';
            el.style.position = 'fixed';
            el.style.right = '12px';
            el.style.top = '12px';
            el.style.padding = '8px 12px';
            el.style.background = 'rgba(16,185,129,0.12)';
            el.style.color = '#10B981';
            el.style.borderRadius = '6px';
            el.style.zIndex = '9999';
            document.body.appendChild(el);
          }
          el.textContent = txt;
        } catch (e) { /* ignore */ }
      };

      if (isConnected) {
        setStatus('Conectado');
      } else {
        setStatus('Esperando token...');
      }
    } catch (e) {}
  }, [isConnected]);

  if (!isConnected) {
    return (
      <div className="studio-theme" style={{
        minHeight: '100vh',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: '24px'
      }}>
        <div style={{
          maxWidth: '500px',
          width: '100%',
          background: 'var(--studio-bg-secondary)',
          padding: '32px',
          borderRadius: 'var(--studio-radius-lg)',
          boxShadow: 'var(--studio-shadow-lg)'
        }}>
          <h1 style={{
            fontSize: 'var(--studio-text-2xl)',
            fontWeight: 'var(--studio-font-bold)',
            marginBottom: '8px',
            color: 'var(--studio-text-primary)'
          }}>
            Studio Panel - AvanzaCast
          </h1>
          <p style={{
            fontSize: 'var(--studio-text-base)',
            color: 'var(--studio-text-muted)',
            marginBottom: '24px'
          }}>
            Ingresa tus credenciales de LiveKit para comenzar
          </p>

          <div style={{ marginBottom: '16px' }}>
            <label style={{
              display: 'block',
              fontSize: 'var(--studio-text-sm)',
              fontWeight: 'var(--studio-font-medium)',
              marginBottom: '8px',
              color: 'var(--studio-text-secondary)'
            }}>
              LiveKit Server URL
            </label>
            <input
              type="text"
              value={credentials.serverUrl}
              onChange={(e) => setCredentials(prev => ({ ...prev, serverUrl: e.target.value }))}
              style={{
                width: '100%',
                padding: '10px 12px',
                background: 'var(--studio-bg-primary)',
                border: '1px solid var(--studio-border)',
                borderRadius: 'var(--studio-radius-md)',
                color: 'var(--studio-text-primary)',
                fontSize: 'var(--studio-text-base)',
                fontFamily: 'var(--studio-font-family)'
              }}
              placeholder="ws://localhost:7880"
            />
          </div>

          <div style={{ marginBottom: '16px' }}>
            <label style={{
              display: 'block',
              fontSize: 'var(--studio-text-sm)',
              fontWeight: 'var(--studio-font-medium)',
              marginBottom: '8px',
              color: 'var(--studio-text-secondary)'
            }}>
              Room Name
            </label>
            <input
              type="text"
              value={credentials.roomName}
              onChange={(e) => setCredentials(prev => ({ ...prev, roomName: e.target.value }))}
              style={{
                width: '100%',
                padding: '10px 12px',
                background: 'var(--studio-bg-primary)',
                border: '1px solid var(--studio-border)',
                borderRadius: 'var(--studio-radius-md)',
                color: 'var(--studio-text-primary)',
                fontSize: 'var(--studio-text-base)',
                fontFamily: 'var(--studio-font-family)'
              }}
              placeholder="Studio Demo"
            />
          </div>

          <div style={{ marginBottom: '24px' }}>
            <label style={{
              display: 'block',
              fontSize: 'var(--studio-text-sm)',
              fontWeight: 'var(--studio-font-medium)',
              marginBottom: '8px',
              color: 'var(--studio-text-secondary)'
            }}>
              Access Token
            </label>
            <textarea
              value={tempToken}
              onChange={(e) => setTempToken(e.target.value)}
              rows={4}
              style={{
                width: '100%',
                padding: '10px 12px',
                background: 'var(--studio-bg-primary)',
                border: '1px solid var(--studio-border)',
                borderRadius: 'var(--studio-radius-md)',
                color: 'var(--studio-text-primary)',
                fontSize: 'var(--studio-text-sm)',
                fontFamily: 'monospace',
                resize: 'vertical'
              }}
              placeholder="Paste your LiveKit token here..."
            />
          </div>

          <Button
            variant="primary"
            fullWidth
            onClick={handleConnect}
            disabled={!tempToken.trim()}
          >
            Conectar al Estudio
          </Button>

          <div style={{
            marginTop: '24px',
            padding: '16px',
            background: 'var(--studio-bg-tertiary)',
            borderRadius: 'var(--studio-radius-md)',
            fontSize: 'var(--studio-text-sm)',
            color: 'var(--studio-text-muted)'
          }}>
            <strong style={{ color: 'var(--studio-text-secondary)' }}>Nota:</strong> Necesitas un token válido de LiveKit para conectar.
            <br />
            <a
              href="https://docs.livekit.io/home/get-started/authentication/"
              target="_blank"
              rel="noopener noreferrer"
              style={{ color: 'var(--studio-accent)', textDecoration: 'none' }}
            >
              Aprende cómo generar un token →
            </a>
          </div>
        </div>
      </div>
    );
  }

  // When connected (we have token), show the StreamYard-like portal
  return (
    <StudioPortal
      serverUrl={credentials.serverUrl}
      token={credentials.token}
      roomName={credentials.roomName}
      onRoomConnected={handleRoomConnected}
      onRoomDisconnected={handleRoomDisconnected}
      room={roomRef.current || undefined}
    />
  );
}

export default App;
