import React, { useEffect, useState, useRef, useCallback } from 'react';
import { getWsUrl } from '../api';

interface ProctorStreamPanelsProps {
  studentId: number;
  layout?: 'default' | 'focus';
}

const ZOOM_STEPS = [0.5, 0.75, 1, 1.25, 1.5, 2, 2.5, 3];

export const ProctorStreamPanels: React.FC<ProctorStreamPanelsProps> = ({
  studentId,
  layout = 'focus',
}) => {
  const [screenFrame, setScreenFrame] = useState<string | null>(null);
  const [webcamFrame, setWebcamFrame] = useState<string | null>(null);
  const [streaming, setStreaming] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [showWebcam, setShowWebcam] = useState(true);
  const [screenZoomIdx, setScreenZoomIdx] = useState(2); // 1x
  const [webcamZoomIdx, setWebcamZoomIdx] = useState(2);
  const [isFullscreen, setIsFullscreen] = useState(false);

  const wsRef = useRef<WebSocket | null>(null);
  const intentionalClose = useRef(false);
  const hasOpened = useRef(false);
  const hasFrames = useRef(false);
  const screenPanelRef = useRef<HTMLDivElement>(null);

  const screenZoom = ZOOM_STEPS[screenZoomIdx];
  const webcamZoom = ZOOM_STEPS[webcamZoomIdx];

  useEffect(() => {
    const wsUrl = getWsUrl('/ws?role=teacher');
    let retryTimer: ReturnType<typeof setTimeout> | null = null;
    let pingTimer: ReturnType<typeof setInterval> | null = null;
    let attempt = 0;

    intentionalClose.current = false;
    hasOpened.current = false;
    hasFrames.current = false;
    setStreaming(false);
    setErrorMessage(null);
    setScreenFrame(null);
    setWebcamFrame(null);

    const markStreaming = () => {
      if (!hasFrames.current) {
        hasFrames.current = true;
        setStreaming(true);
        setErrorMessage(null);
      }
    };

    const clearPing = () => {
      if (pingTimer) {
        clearInterval(pingTimer);
        pingTimer = null;
      }
    };

    const connect = () => {
      if (intentionalClose.current) return;

      const ws = new WebSocket(wsUrl);
      wsRef.current = ws;

      ws.onopen = () => {
        attempt = 0;
        hasOpened.current = true;
        setStreaming(true);
        setErrorMessage(null);
        ws.send(JSON.stringify({ event: 'teacher:subscribe', data: { studentId } }));
        clearPing();
        pingTimer = setInterval(() => {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({ event: 'client:ping', data: {} }));
          }
        }, 15000);
      };

      ws.onmessage = (event) => {
        try {
          const msg = JSON.parse(event.data);
          if (msg.event === 'client:pong') return;
          if (msg.event === 'teacher:screenshot-stream-frame' && msg.data.studentId === studentId) {
            setScreenFrame(msg.data.imageBuffer);
            markStreaming();
          } else if (msg.event === 'teacher:webcam-stream-frame' && msg.data.studentId === studentId) {
            setWebcamFrame(msg.data.imageBuffer);
            markStreaming();
          } else if (msg.event === 'teacher:stream-stopped' && msg.data.studentId === studentId) {
            setScreenFrame(null);
            setWebcamFrame(null);
            setStreaming(false);
            setErrorMessage('Sinh viên đã dừng stream');
          }
        } catch (err) {
          console.error('Error parsing WS frame:', err);
        }
      };

      ws.onerror = () => {};

      ws.onclose = () => {
        clearPing();
        if (intentionalClose.current) return;
        setStreaming(false);
        if (!hasOpened.current && !hasFrames.current) {
          setErrorMessage('Không thể kết nối máy chủ giám sát');
        } else {
          setErrorMessage('Mất kết nối giám sát — đang thử lại...');
        }
        const delay = Math.min(1000 * 2 ** Math.min(attempt++, 4), 10000);
        retryTimer = setTimeout(connect, delay);
      };
    };

    connect();

    return () => {
      intentionalClose.current = true;
      clearPing();
      if (retryTimer) clearTimeout(retryTimer);
      if (wsRef.current?.readyState === WebSocket.OPEN) {
        wsRef.current.send(JSON.stringify({ event: 'teacher:unsubscribe', data: { studentId } }));
      }
      wsRef.current?.close();
      wsRef.current = null;
    };
  }, [studentId]);

  useEffect(() => {
    const onFsChange = () => {
      setIsFullscreen(document.fullscreenElement === screenPanelRef.current);
    };
    document.addEventListener('fullscreenchange', onFsChange);
    return () => document.removeEventListener('fullscreenchange', onFsChange);
  }, []);

  const toggleFullscreen = useCallback(async () => {
    const el = screenPanelRef.current;
    if (!el) return;
    try {
      if (document.fullscreenElement === el) {
        await document.exitFullscreen();
      } else {
        await el.requestFullscreen();
      }
    } catch (e) {
      console.error('Fullscreen error', e);
    }
  }, []);

  const zoomIn = (target: 'screen' | 'webcam') => {
    const setter = target === 'screen' ? setScreenZoomIdx : setWebcamZoomIdx;
    setter(i => Math.min(i + 1, ZOOM_STEPS.length - 1));
  };

  const zoomOut = (target: 'screen' | 'webcam') => {
    const setter = target === 'screen' ? setScreenZoomIdx : setWebcamZoomIdx;
    setter(i => Math.max(i - 1, 0));
  };

  const zoomReset = (target: 'screen' | 'webcam') => {
    if (target === 'screen') setScreenZoomIdx(2);
    else setWebcamZoomIdx(2);
  };

  const renderZoomToolbar = (target: 'screen' | 'webcam', zoom: number, onFs?: () => void) => (
    <div className="panel-toolbar">
      <button type="button" className="proctor-tool-btn" title="Thu nhỏ" onClick={() => zoomOut(target)}>−</button>
      <span className="proctor-zoom-label">{Math.round(zoom * 100)}%</span>
      <button type="button" className="proctor-tool-btn" title="Phóng to" onClick={() => zoomIn(target)}>+</button>
      <button type="button" className="proctor-tool-btn" title="Về 100%" onClick={() => zoomReset(target)}>1:1</button>
      {onFs && (
        <button type="button" className="proctor-tool-btn proctor-tool-btn-wide" title="Toàn màn hình" onClick={onFs}>
          {isFullscreen ? 'Thu nhỏ' : 'Phóng to'}
        </button>
      )}
    </div>
  );

  return (
    <div className="proctor-stream-wrap">
      <div className="proctor-stream-toolbar">
        <span className={`status-pill ${streaming || screenFrame || webcamFrame ? 'connected' : 'connecting'}`}>
          {streaming || screenFrame || webcamFrame ? '● Đang phát' : '○ Đang kết nối...'}
        </span>
        <div className="proctor-stream-actions">
          <button
            type="button"
            className={`btn btn-secondary proctor-action-btn ${showWebcam ? '' : 'active'}`}
            onClick={() => setShowWebcam(v => !v)}
          >
            {showWebcam ? 'Ẩn webcam' : 'Hiện webcam'}
          </button>
        </div>
      </div>

      {errorMessage && !screenFrame && !webcamFrame && (
        <div className="alert-error proctor-stream-error">{errorMessage}</div>
      )}

      <div className={`proctor-grid proctor-grid-${layout} ${!showWebcam ? 'proctor-grid--no-webcam' : ''}`}>
        <div
          className={`proctor-panel screen-panel ${isFullscreen ? 'screen-panel--fullscreen' : ''}`}
          ref={screenPanelRef}
        >
          <div className="panel-title-row">
            <span className="panel-title-text">Màn hình sinh viên</span>
            {renderZoomToolbar('screen', screenZoom, toggleFullscreen)}
          </div>
          <div className="panel-body screen-body" onDoubleClick={toggleFullscreen} title="Double-click để phóng to">
            <div className="proctor-zoom-viewport">
              {screenFrame ? (
                <img
                  src={screenFrame}
                  alt="Màn hình sinh viên"
                  className="live-frame screen-img"
                  style={{ transform: `scale(${screenZoom})` }}
                  draggable={false}
                />
              ) : (
                <div className="no-stream-placeholder"><p>Đang chờ màn hình...</p></div>
              )}
            </div>
          </div>
        </div>

        {showWebcam && (
          <div className="proctor-panel webcam-panel">
            <div className="panel-title-row">
              <span className="panel-title-text">Webcam</span>
              {renderZoomToolbar('webcam', webcamZoom)}
            </div>
            <div className="panel-body webcam-body">
              <div className="proctor-zoom-viewport proctor-zoom-viewport--webcam">
                {webcamFrame ? (
                  <img
                    src={webcamFrame}
                    alt="Webcam sinh viên"
                    className="live-frame webcam-img"
                    style={{ transform: `scale(${webcamZoom})` }}
                    draggable={false}
                  />
                ) : (
                  <div className="no-stream-placeholder"><p>Đang chờ webcam...</p></div>
                )}
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};
