import React, { useEffect, useState, useRef, useMemo } from 'react';
import { getWsUrl, type ExamRoomStudent } from '../api';
import { openStaffChat } from '../chatEvents';

interface ExamGridProctorProps {
  students: ExamRoomStudent[];
  onlineIds: number[];
  onSelectStudent: (student: ExamRoomStudent) => void;
}

export const ExamGridProctor: React.FC<ExamGridProctorProps> = ({
  students,
  onlineIds,
  onSelectStudent,
}) => {
  const [screenFrames, setScreenFrames] = useState<Record<number, string>>({});
  const [webcamFrames, setWebcamFrames] = useState<Record<number, string>>({});
  const [gridCols, setGridCols] = useState<number>(3);
  const [showWebcamOverlay, setShowWebcamOverlay] = useState<boolean>(true);
  const [searchQuery, setSearchQuery] = useState<string>('');
  const [onlyOnline, setOnlyOnline] = useState<boolean>(false);
  const [isFullscreen, setIsFullscreen] = useState<boolean>(false);

  const wsRef = useRef<WebSocket | null>(null);
  const subscribedRef = useRef<Set<number>>(new Set());
  const gridContainerRef = useRef<HTMLDivElement>(null);

  const studentIdsString = useMemo(
    () => students.map((s) => s.studentRkId).join(','),
    [students]
  );
  const onlineKey = useMemo(() => onlineIds.join(','), [onlineIds]);

  const onlineIdsRef = useRef<number[]>(onlineIds);
  onlineIdsRef.current = onlineIds;

  const syncSubscriptions = (ws: WebSocket) => {
    if (ws.readyState !== WebSocket.OPEN) return;
    const currentOnlineIds = onlineIdsRef.current;
    const target = new Set(currentOnlineIds);
    const prev = subscribedRef.current;

    prev.forEach((id) => {
      if (!target.has(id)) {
        ws.send(JSON.stringify({ event: 'teacher:unsubscribe', data: { studentId: id } }));
        prev.delete(id);
      }
    });
    currentOnlineIds.forEach((id) => {
      if (!prev.has(id)) {
        ws.send(JSON.stringify({ event: 'teacher:subscribe', data: { studentId: id } }));
        prev.add(id);
      }
    });
  };

  useEffect(() => {
    if (students.length === 0) return;

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

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

    const connect = () => {
      if (closed) return;

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

      ws.onopen = () => {
        attempt = 0;
        syncSubscriptions(ws);
        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') {
            const { studentId, imageBuffer } = msg.data;
            setScreenFrames((prev) => ({ ...prev, [studentId]: imageBuffer }));
          } else if (msg.event === 'teacher:webcam-stream-frame') {
            const { studentId, imageBuffer } = msg.data;
            setWebcamFrames((prev) => ({ ...prev, [studentId]: imageBuffer }));
          } else if (msg.event === 'teacher:stream-stopped') {
            const { studentId } = msg.data;
            setScreenFrames((prev) => {
              const next = { ...prev };
              delete next[studentId];
              return next;
            });
            setWebcamFrames((prev) => {
              const next = { ...prev };
              delete next[studentId];
              return next;
            });
          }
        } catch (err) {
          console.error('Error parsing WS message in grid view:', err);
        }
      };

      ws.onclose = () => {
        clearPing();
        subscribedRef.current = new Set();
        if (!closed) {
          const delay = Math.min(1000 * 2 ** Math.min(attempt++, 4), 10000);
          retryTimer = setTimeout(connect, delay);
        }
      };
    };

    connect();

    return () => {
      closed = true;
      clearPing();
      if (retryTimer) clearTimeout(retryTimer);
      const ws = wsRef.current;
      if (ws?.readyState === WebSocket.OPEN) {
        subscribedRef.current.forEach((id) => {
          ws.send(JSON.stringify({ event: 'teacher:unsubscribe', data: { studentId: id } }));
        });
      }
      ws?.close();
      wsRef.current = null;
      subscribedRef.current = new Set();
    };
  }, [studentIdsString]);

  useEffect(() => {
    const ws = wsRef.current;
    if (ws) syncSubscriptions(ws);
  }, [onlineKey]);

  // Clean up frames when students are removed or go offline
  useEffect(() => {
    setScreenFrames((prev) => {
      const next = { ...prev };
      let changed = false;
      Object.keys(next).forEach((idStr) => {
        const id = Number(idStr);
        if (!onlineIds.includes(id)) {
          delete next[id];
          changed = true;
        }
      });
      return changed ? next : prev;
    });
    setWebcamFrames((prev) => {
      const next = { ...prev };
      let changed = false;
      Object.keys(next).forEach((idStr) => {
        const id = Number(idStr);
        if (!onlineIds.includes(id)) {
          delete next[id];
          changed = true;
        }
      });
      return changed ? next : prev;
    });
  }, [onlineIds]);

  const filteredStudents = useMemo(() => {
    return students.filter((s) => {
      const matchesSearch =
        s.fullName.toLowerCase().includes(searchQuery.toLowerCase()) ||
        s.studentCode.toLowerCase().includes(searchQuery.toLowerCase());
      const isOnline = onlineIds.includes(s.studentRkId);
      const matchesOnlineFilter = !onlyOnline || isOnline;
      return matchesSearch && matchesOnlineFilter;
    });
  }, [students, onlineIds, searchQuery, onlyOnline]);

  const handleOpenChat = (s: ExamRoomStudent, e: React.MouseEvent) => {
    e.stopPropagation();
    openStaffChat({
      studentRkId: s.studentRkId,
      fullName: s.fullName,
      studentCode: s.studentCode,
      email: s.email,
    });
  };

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

  const toggleFullscreen = () => {
    const el = gridContainerRef.current;
    if (!el) return;
    if (document.fullscreenElement === el) {
      document.exitFullscreen().catch(console.error);
    } else {
      el.requestFullscreen().catch(console.error);
    }
  };

  return (
    <div className="grid-proctor-container" ref={gridContainerRef}>
      <div className="grid-proctor-toolbar">
        <div className="grid-proctor-toolbar-left">
          <div className="search-input-wrapper">
            <input
              type="text"
              className="search-input"
              placeholder="Lọc sinh viên..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
            />
            <span className="search-icon">🔍</span>
          </div>

          <label className="checkbox-label" style={{ display: 'flex', alignItems: 'center', gap: '0.35rem', cursor: 'pointer', fontSize: '0.85rem' }}>
            <input
              type="checkbox"
              checked={onlyOnline}
              onChange={(e) => setOnlyOnline(e.target.checked)}
            />
            <span>Chỉ hiện Online</span>
          </label>

          <label className="checkbox-label" style={{ display: 'flex', alignItems: 'center', gap: '0.35rem', cursor: 'pointer', fontSize: '0.85rem' }}>
            <input
              type="checkbox"
              checked={showWebcamOverlay}
              onChange={(e) => setShowWebcamOverlay(e.target.checked)}
            />
            <span>Đè webcam góc màn hình</span>
          </label>
        </div>

        <div className="grid-proctor-toolbar-right">
          <div className="grid-cols-selector">
            <span style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>Cột:</span>
            <button
              type="button"
              className={`btn btn-secondary btn-xs ${gridCols === 2 ? 'active' : ''}`}
              onClick={() => setGridCols(2)}
            >
              2
            </button>
            <button
              type="button"
              className={`btn btn-secondary btn-xs ${gridCols === 3 ? 'active' : ''}`}
              onClick={() => setGridCols(3)}
            >
              3
            </button>
            <button
              type="button"
              className={`btn btn-secondary btn-xs ${gridCols === 4 ? 'active' : ''}`}
              onClick={() => setGridCols(4)}
            >
              4
            </button>
            <button
              type="button"
              className={`btn btn-secondary btn-xs ${gridCols === 6 ? 'active' : ''}`}
              onClick={() => setGridCols(6)}
            >
              6
            </button>
          </div>

          <button
            type="button"
            className="btn btn-secondary btn-sm"
            onClick={toggleFullscreen}
          >
            {isFullscreen ? '🖥️ Thu nhỏ' : '🖥️ Toàn màn hình'}
          </button>
        </div>
      </div>

      <div
        className={`grid-proctor-layout`}
        style={{
          display: 'grid',
          gridTemplateColumns: `repeat(${gridCols}, minmax(0, 1fr))`,
          gap: '1rem',
          padding: '1rem 0',
        }}
      >
        {filteredStudents.map((s) => {
          const isOnline = onlineIds.includes(s.studentRkId);
          const screenFrame = screenFrames[s.studentRkId];
          const webcamFrame = webcamFrames[s.studentRkId];

          return (
            <div
              key={s.id}
              className={`grid-proctor-card ${isOnline ? 'online' : 'offline'} ${s.submitted ? 'submitted' : ''}`}
              onClick={() => onSelectStudent(s)}
            >
              <div className="grid-proctor-card-header">
                <div className="student-info-left">
                  <span className={`status-dot ${isOnline ? 'online' : 'offline'}`} />
                  <span className="student-name" title={s.fullName}>
                    {s.fullName}
                  </span>
                </div>
                <span className="student-code">{s.studentCode}</span>
              </div>

              <div className="grid-proctor-card-body">
                {isOnline ? (
                  <div className="proctor-frame-container">
                    {screenFrame ? (
                      <img
                        src={screenFrame}
                        alt={`Màn hình ${s.fullName}`}
                        className="proctor-screen-image"
                        draggable={false}
                      />
                    ) : (
                      <div className="proctor-placeholder streaming">
                        <div className="sync-spinner" style={{ width: '20px', height: '20px', borderWidth: '2px', marginBottom: '0.5rem' }} />
                        <span>Đang kết nối màn hình...</span>
                      </div>
                    )}

                    {showWebcamOverlay && webcamFrame && (
                      <div className="proctor-webcam-overlay">
                        <img
                          src={webcamFrame}
                          alt={`Webcam ${s.fullName}`}
                          className="proctor-webcam-image"
                          draggable={false}
                        />
                      </div>
                    )}
                  </div>
                ) : (
                  <div className="proctor-placeholder offline">
                    <span className="icon">📴</span>
                    <span>Ngoại tuyến (Offline)</span>
                  </div>
                )}
              </div>

              <div className="grid-proctor-card-footer" onClick={(e) => e.stopPropagation()}>
                <span className="assigned-paper" title={s.paperTitle || 'Chưa gán đề'}>
                  {s.paperTitle ? `Đề: ${s.paperTitle}` : 'Chưa gán đề'}
                </span>
                <div className="footer-actions">
                  <button
                    type="button"
                    className="btn btn-ghost btn-xs text-primary"
                    onClick={(e) => handleOpenChat(s, e)}
                    title="Nhắn tin cho sinh viên"
                  >
                    💬 Nhắn tin
                  </button>
                  <button
                    type="button"
                    className="btn btn-ghost btn-xs"
                    onClick={() => onSelectStudent(s)}
                    title="Xem chi tiết giám sát"
                  >
                    🔍 Giám sát
                  </button>
                </div>
              </div>
            </div>
          );
        })}

        {filteredStudents.length === 0 && (
          <div className="grid-proctor-empty" style={{ gridColumn: '1 / -1' }}>
            <span>🔍</span>
            <p>Không tìm thấy sinh viên nào.</p>
          </div>
        )}
      </div>
    </div>
  );
};
