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 [zoomedStudent, setZoomedStudent] = useState<ExamRoomStudent | null>(null);
  const [pageSize, setPageSize] = useState<number | 'all'>(12);
  const [currentPage, setCurrentPage] = useState<number>(1);

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

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        setZoomedStudent(null);
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, []);

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

  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 pagedStudents = useMemo(() => {
    if (pageSize === 'all') return filteredStudents;
    const start = (currentPage - 1) * pageSize;
    return filteredStudents.slice(start, start + pageSize);
  }, [filteredStudents, currentPage, pageSize]);

  const totalPages = useMemo(() => {
    if (pageSize === 'all') return 1;
    return Math.ceil(filteredStudents.length / pageSize) || 1;
  }, [filteredStudents, pageSize]);

  useEffect(() => {
    if (currentPage > totalPages) {
      setCurrentPage(totalPages);
    }
  }, [totalPages, currentPage]);

  const visibleOnlineIds = useMemo(() => {
    return pagedStudents
      .map((s) => s.studentRkId)
      .filter((id) => onlineIds.includes(id));
  }, [pagedStudents, onlineIds]);

  const visibleOnlineIdsRef = useRef<number[]>(visibleOnlineIds);
  visibleOnlineIdsRef.current = visibleOnlineIds;

  const onlineKey = useMemo(() => visibleOnlineIds.join(','), [visibleOnlineIds]);

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

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

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

  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]);

  // 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 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 ${isFullscreen ? 'fullscreen-active' : ''}`} 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', color: 'var(--text-primary)' }}>
            <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', color: 'var(--text-primary)' }}>
            <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" style={{ display: 'flex', alignItems: 'center', gap: '0.35rem' }}>
            <span style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>Xem tối đa:</span>
            <select
              value={pageSize}
              onChange={(e) => {
                const val = e.target.value;
                setPageSize(val === 'all' ? 'all' : Number(val));
                setCurrentPage(1);
              }}
              style={{
                fontSize: '0.75rem',
                padding: '0.2rem 0.4rem',
                borderRadius: '4px',
                border: '1px solid var(--border-color)',
                backgroundColor: 'var(--bg-card)',
                color: 'var(--text-primary)',
                fontWeight: 600,
                cursor: 'pointer',
              }}
            >
              <option value={12}>12 bạn</option>
              <option value={24}>24 bạn</option>
              <option value={48}>48 bạn</option>
              <option value="all">Tất cả</option>
            </select>
          </div>

          <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',
        }}
      >
        {pagedStudents.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 cursor-zoom-in"
                    onClick={(e) => {
                      e.stopPropagation();
                      setZoomedStudent(s);
                    }}
                    style={{ cursor: 'zoom-in' }}
                  >
                    {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>

      {/* Pagination Controls */}
      {totalPages > 1 && (
        <div
          className="grid-proctor-pagination"
          style={{
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            gap: '1rem',
            padding: '1rem 0',
            borderTop: '1px solid var(--border-light)',
            marginTop: '1.25rem',
          }}
        >
          <button
            type="button"
            className="btn btn-secondary btn-sm"
            disabled={currentPage === 1}
            onClick={() => setCurrentPage((p) => Math.max(p - 1, 1))}
            style={{ fontWeight: 600 }}
          >
            &larr; Trang trước
          </button>
          <span style={{ fontSize: '0.85rem', color: 'var(--text-secondary)', fontWeight: 600 }}>
            Trang {currentPage} / {totalPages} (Tổng {filteredStudents.length} bạn)
          </span>
          <button
            type="button"
            className="btn btn-secondary btn-sm"
            disabled={currentPage === totalPages}
            onClick={() => setCurrentPage((p) => Math.min(p + 1, totalPages))}
            style={{ fontWeight: 600 }}
          >
            Trang sau &rarr;
          </button>
        </div>
      )}

      {/* Zoom Modal Overlay (Rendered inside the container so it works in fullscreen mode) */}
      {zoomedStudent && (
        <div
          className="zoomed-proctor-overlay"
          onClick={() => setZoomedStudent(null)}
          style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            backgroundColor: 'rgba(10, 15, 30, 0.9)',
            backdropFilter: 'blur(8px)',
            zIndex: 9999,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            padding: '2rem',
            animation: 'fadeIn 0.2s ease-out',
          }}
        >
          <div
            className="zoomed-proctor-modal"
            onClick={(e) => e.stopPropagation()}
            style={{
              width: '100%',
              maxWidth: '1000px',
              backgroundColor: 'var(--bg-card)',
              border: '1px solid var(--border-color)',
              borderRadius: '16px',
              boxShadow: '0 20px 40px rgba(0, 0, 0, 0.4)',
              display: 'flex',
              flexDirection: 'column',
              maxHeight: '90%',
              overflow: 'hidden',
            }}
          >
            {/* Modal Header */}
            <div
              style={{
                display: 'flex',
                justifyContent: 'space-between',
                alignItems: 'center',
                padding: '1rem 1.5rem',
                borderBottom: '1px solid var(--border-color)',
                backgroundColor: 'var(--bg-subtle)',
              }}
            >
              <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
                <span
                  style={{
                    width: '10px',
                    height: '10px',
                    borderRadius: '50%',
                    backgroundColor: onlineIds.includes(zoomedStudent.studentRkId) ? 'var(--success)' : 'var(--danger)',
                    boxShadow: onlineIds.includes(zoomedStudent.studentRkId) ? '0 0 8px var(--success)' : 'none',
                  }}
                />
                <h3 style={{ margin: 0, color: 'var(--text-primary)', fontSize: '1.1rem', fontWeight: 600 }}>
                  {zoomedStudent.fullName}
                </h3>
                <span
                  style={{
                    fontFamily: 'monospace',
                    fontSize: '0.85rem',
                    color: 'var(--text-secondary)',
                    backgroundColor: 'var(--bg-subtle)',
                    padding: '2px 8px',
                    borderRadius: '4px',
                  }}
                >
                  {zoomedStudent.studentCode}
                </span>
              </div>
              <button
                onClick={() => setZoomedStudent(null)}
                style={{
                  background: 'none',
                  border: 'none',
                  color: 'var(--text-secondary)',
                  fontSize: '1.5rem',
                  cursor: 'pointer',
                  padding: '4px 8px',
                  lineHeight: 1,
                }}
              >
                &times;
              </button>
            </div>

            {/* Modal Body */}
            <div
              style={{
                flex: 1,
                padding: '1.5rem',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                backgroundColor: '#000',
                position: 'relative',
                minHeight: '400px',
                overflow: 'hidden',
              }}
            >
              {screenFrames[zoomedStudent.studentRkId] ? (
                <div style={{ position: 'relative', width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
                  <img
                    src={screenFrames[zoomedStudent.studentRkId]}
                    alt="Zoomed Screen"
                    style={{
                      maxWidth: '100%',
                      maxHeight: '65vh',
                      objectFit: 'contain',
                      borderRadius: '8px',
                    }}
                  />
                  {showWebcamOverlay && webcamFrames[zoomedStudent.studentRkId] && (
                    <div
                      style={{
                        position: 'absolute',
                        bottom: '20px',
                        right: '20px',
                        width: '240px',
                        aspectRatio: '4/3',
                        borderRadius: '8px',
                        border: '2px solid #ffffff',
                        boxShadow: '0 8px 16px rgba(0, 0, 0, 0.4)',
                        overflow: 'hidden',
                        backgroundColor: '#000',
                      }}
                    >
                      <img
                        src={webcamFrames[zoomedStudent.studentRkId]}
                        alt="Zoomed Webcam"
                        style={{ width: '100%', height: '100%', objectFit: 'cover' }}
                      />
                    </div>
                  )}
                </div>
              ) : (
                <div style={{ color: '#8e8e9e', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '12px' }}>
                  <div className="sync-spinner" style={{ width: '32px', height: '32px', borderWidth: '3px', marginBottom: '0.5rem' }} />
                  <span>Đang tải màn hình...</span>
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      <style>{`
        .cursor-zoom-in {
          transition: transform 0.2s ease, box-shadow 0.2s ease;
        }
        .cursor-zoom-in:hover {
          transform: scale(1.015);
          box-shadow: 0 6px 16px rgba(0,0,0,0.3);
        }
        @keyframes fadeIn {
          from { opacity: 0; }
          to { opacity: 1; }
        }
      `}</style>
    </div>
  );
};
