/**
 * Copyright 2024 Google LLC
 * ... (لایسنس و توضیحات دیگر مثل قبل) ...
 */

import cn from "classnames";
import { memo, ReactNode, RefObject, useEffect, useRef, useState } from "react";
import { useLiveAPIContext } from "../../contexts/LiveAPIContext";
import { UseMediaStreamResult } from "../../hooks/use-media-stream-mux";
import { useScreenCapture } from "../../hooks/use-screen-capture";
import { useWebcam } from "../../hooks/use-webcam";
import { AudioRecorder } from "../../lib/audio-recorder";
import { isIOS } from "../../lib/platform";
import AudioPulse from "../audio-pulse/AudioPulse";
import "./control-tray.scss";

export type ControlTrayProps = {
  videoRef: RefObject<HTMLVideoElement>;
  children?: ReactNode;
  supportsVideo: boolean;
  onVideoStreamChange?: (stream: MediaStream | null) => void;
};

type MediaStreamButtonProps = {
  isStreaming: boolean;
  onIcon: string;
  offIcon: string;
  start: () => Promise<any>;
  stop: () => any;
  disabled?: boolean;
};

const MediaStreamButton = memo(
  ({ isStreaming, onIcon, offIcon, start, stop, disabled }: MediaStreamButtonProps) =>
    isStreaming ? (
      <button className="action-button" onClick={stop} title={`Stop ${offIcon}`} disabled={disabled}>
        <span className="material-symbols-outlined">{onIcon}</span>
      </button>
    ) : (
      <button className="action-button" onClick={start} title={`Start ${offIcon}`} disabled={disabled}>
        <span className="material-symbols-outlined">{offIcon}</span>
      </button>
    ),
);

function ControlTray({
  videoRef,
  children,
  onVideoStreamChange = () => {},
  supportsVideo,
}: ControlTrayProps) {
  const webcam = useWebcam();
  const screenCapture = useScreenCapture();

  const [activeVideoStream, setActiveVideoStream] = useState<MediaStream | null>(null);
  const [currentFacingMode, setCurrentFacingMode] = useState<'user' | 'environment' | null>(null);
  const [isSwitchingCamera, setIsSwitchingCamera] = useState(false);
  const [isLikelyDesktop, setIsLikelyDesktop] = useState(false); // <-- State برای تشخیص دسکتاپ
  const [inVolume, setInVolume] = useState(0);
  const [audioRecorder] = useState(() => new AudioRecorder());
  const [muted, setMuted] = useState(false);
  const renderCanvasRef = useRef<HTMLCanvasElement>(null);
  const connectButtonRef = useRef<HTMLButtonElement>(null);
  const [simulatedVolume, setSimulatedVolume] = useState(0);
  const isIOSDevice = isIOS();

  const { client, connected, connect, disconnect, volume } = useLiveAPIContext();
  const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

  // --- useEffect ها ---

  // بررسی نوع دستگاه (دسکتاپ یا موبایل/تبلت) در زمان Mount
  useEffect(() => {
    // navigator.maxTouchPoints > 0 معمولا نشان‌دهنده دستگاه لمسی است
    const desktopCheck = typeof navigator !== 'undefined' && navigator.maxTouchPoints <= 0;
    setIsLikelyDesktop(desktopCheck);
    console.log(`Device check: Likely Desktop? ${desktopCheck} (maxTouchPoints: ${navigator.maxTouchPoints})`);
  }, []); // فقط یک بار در زمان Mount اجرا شود

  // Focus effect
  useEffect(() => {
    if (!connected && connectButtonRef.current) {
      connectButtonRef.current.focus();
    }
  }, [connected]);

  // iOS volume simulation
  useEffect(() => {
    let interval: number | undefined;
    if (isIOSDevice && connected && !muted) {
      interval = window.setInterval(() => {
        const pulse = (Math.sin(Date.now() / 500) + 1) / 2;
        setSimulatedVolume(0.02 + pulse * 0.03);
      }, 50);
    }
    return () => {
      if (interval) clearInterval(interval);
    };
  }, [connected, muted, isIOSDevice]);

  // CSS volume update
  useEffect(() => {
    document.documentElement.style.setProperty(
      "--volume",
      `${Math.max(5, Math.min((isIOSDevice ? simulatedVolume : inVolume) * 200, 8))}px`,
    );
  }, [inVolume, simulatedVolume, isIOSDevice]);

  // Audio recording
  useEffect(() => {
    const onData = (base64: string) => {
      if (client && connected) {
        client.sendRealtimeInput([{ mimeType: "audio/pcm;rate=16000", data: base64 }]);
      }
    };
    if (connected && !muted && audioRecorder) {
      audioRecorder.on("data", onData).on("volume", setInVolume).start();
    } else if (audioRecorder) {
      audioRecorder.stop();
    }
    return () => {
      if (audioRecorder) {
        audioRecorder.off("data", onData).off("volume", setInVolume).stop();
      }
    };
  }, [connected, client, muted, audioRecorder]);

  // Stop video on disconnect
  useEffect(() => {
    if (!connected && activeVideoStream) {
      console.log('🔌 Disconnected, stopping video stream.');
      activeVideoStream.getTracks().forEach(track => track.stop());
      setActiveVideoStream(null);
      onVideoStreamChange(null);
      setCurrentFacingMode(null);
      setIsSwitchingCamera(false);
      webcam.stop();
      screenCapture.stop();
    }
  }, [connected, activeVideoStream, onVideoStreamChange, webcam, screenCapture]);

  // Video frame sending
  useEffect(() => {
    let timeoutId = -1;
    function sendVideoFrame() {
      if (connected && activeVideoStream) {
        timeoutId = window.setTimeout(sendVideoFrame, 1000 / 0.5);
      }
      const video = videoRef.current; const canvas = renderCanvasRef.current;
      if (!video || !canvas || video.readyState < video.HAVE_METADATA || video.paused || video.ended || !client) return;
      try {
        const ctx = canvas.getContext("2d"); if (!ctx) return;
        const scale = 0.25; canvas.width = video.videoWidth * scale; canvas.height = video.videoHeight * scale;
        if (canvas.width > 0 && canvas.height > 0) {
          ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
          const base64 = canvas.toDataURL("image/jpeg", 0.8);
          const data = base64.slice(base64.indexOf(",") + 1);
          client.sendRealtimeInput([{ mimeType: "image/jpeg", data }]);
        }
      } catch (error) { console.error("❌ Error processing video frame:", error); }
    }
    if (connected && activeVideoStream && videoRef.current) { setTimeout(sendVideoFrame, 200); }
    return () => { clearTimeout(timeoutId); };
  }, [connected, activeVideoStream, client, videoRef]);

  // Assign stream to video element
  useEffect(() => {
    if (videoRef.current) {
      if (videoRef.current.srcObject !== activeVideoStream) {
        videoRef.current.srcObject = activeVideoStream;
        if (activeVideoStream) { videoRef.current.play().catch(e => console.warn("Video play failed:", e)); }
      }
    }
  }, [activeVideoStream, videoRef]);
  // --- پایان useEffect ها ---


  // Function to stop all video streams
  const stopAllVideoStreams = () => {
    console.log('⏹️ Stopping all video streams...');
    if (activeVideoStream) {
      activeVideoStream.getTracks().forEach(track => track.stop());
      setActiveVideoStream(null);
      onVideoStreamChange(null);
    }
    webcam.stop(); screenCapture.stop(); setCurrentFacingMode(null); setIsSwitchingCamera(false);
  };

  // Handler for starting/stopping webcam or screen share
  const changeStreams = (streamType: 'webcam' | 'screen' | 'none') => async () => {
    if (isSwitchingCamera) return;
    // Only allow starting screen share if it's likely a desktop
    if (streamType === 'screen' && !isLikelyDesktop) {
        console.warn("Screen share requested on non-desktop device, ignoring.");
        return;
    }

    stopAllVideoStreams();

    if (streamType === 'webcam') {
      const initialFacingMode = 'user'; console.log(`🚀 Starting webcam with initial facingMode: ${initialFacingMode}`);
      try {
        const mediaStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: initialFacingMode }, audio: false });
        setActiveVideoStream(mediaStream); onVideoStreamChange(mediaStream); setCurrentFacingMode(initialFacingMode);
      } catch (error) {
        console.error(`❌ Error starting webcam with ${initialFacingMode}:`, error);
        try { // Fallback
            const fallbackStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false });
            setActiveVideoStream(fallbackStream); onVideoStreamChange(fallbackStream); setCurrentFacingMode('environment');
        } catch (fallbackError) { console.error('❌ Error starting webcam fallback:', fallbackError); setActiveVideoStream(null); onVideoStreamChange(null); setCurrentFacingMode(null); }
      }
    } else if (streamType === 'screen' && isLikelyDesktop) { // Double check desktop condition
      console.log('🚀 Starting screen capture');
      try {
        const mediaStream = await screenCapture.start();
        setActiveVideoStream(mediaStream); onVideoStreamChange(mediaStream); setCurrentFacingMode(null);
      } catch (error) { console.error('❌ Error starting screen capture:', error); setActiveVideoStream(null); onVideoStreamChange(null); setCurrentFacingMode(null); }
    } else { console.log('ℹ️ Video stream turned off or invalid request.'); }
  };

  // Handler for rotating webcam
  const rotateWebcam = async () => {
    if (isSwitchingCamera || !activeVideoStream || currentFacingMode === null) return;
    const targetFacingMode = currentFacingMode === 'user' ? 'environment' : 'user';
    console.log(`🔄 Rotating webcam... Target: ${targetFacingMode}`);
    setIsSwitchingCamera(true);
    activeVideoStream.getTracks().forEach(track => track.stop()); // Stop tracks only

    try {
      const newStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: targetFacingMode } }, audio: false });
      if (videoRef.current) { videoRef.current.srcObject = newStream; videoRef.current.play().catch(e => console.warn("Play fail switch:", e)); }
      setActiveVideoStream(newStream); onVideoStreamChange(newStream); setCurrentFacingMode(targetFacingMode);
    } catch (error: any) {
      console.error(`❌ Error switching camera:`, error.name);
      let recoveredStream: MediaStream | null = null; // Fallback logic...
      if (error.name === 'OverconstrainedError' || error.name === 'ConstraintNotSatisfiedError') {
          try { recoveredStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: targetFacingMode }, audio: false }); setCurrentFacingMode(targetFacingMode); } catch (retryError: any) { console.error(`Retry fail:`, retryError.name); }
      }
      if (!recoveredStream) { try { recoveredStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: currentFacingMode } }, audio: false }); } catch (restoreError) { console.error(`Restore fail:`, restoreError); } }
      if (recoveredStream) { if (videoRef.current) { videoRef.current.srcObject = recoveredStream; videoRef.current.play().catch(e => console.warn("Play fail recovery:", e)); } setActiveVideoStream(recoveredStream); onVideoStreamChange(recoveredStream); }
      else { if (videoRef.current) videoRef.current.srcObject = null; setActiveVideoStream(null); onVideoStreamChange(null); setCurrentFacingMode(null); }
    } finally {
      setIsSwitchingCamera(false);
    }
  };

  // Determine stable streaming states
  const isWebcamStableStreaming = activeVideoStream !== null && currentFacingMode !== null;
  const isScreenCaptureStreaming = screenCapture.isStreaming && activeVideoStream !== null && currentFacingMode === null;

  // Determine if the webcam button should appear active
  const showWebcamAsActive = isWebcamStableStreaming || (isSwitchingCamera && currentFacingMode !== null);

  // **** Condition to show Screen Share Button ****
  const showScreenShareButton = supportsVideo && !isIOSDevice && isLikelyDesktop;


  return (
    <section className="control-tray">
      <canvas style={{ display: "none" }} ref={renderCanvasRef} />

      <nav className={cn("actions-nav", { disabled: !connected })}>
        {/* Mic Button */}
        <button
          className={cn("action-button mic-button")}
          onClick={() => setMuted(!muted)}
          disabled={!connected || isSwitchingCamera}
          title={muted ? "Unmute Microphone" : "Mute Microphone"}
        >
          <span className="material-symbols-outlined filled">{muted ? "mic_off" : "mic"}</span>
        </button>

        {/* Volume Indicator */}
        <div className="action-button no-action outlined">
          <AudioPulse volume={volume} active={connected && !muted} hover={false} />
        </div>

        {/* Video Controls */}
        {supportsVideo && (
          <>
            {/* Screen Share Button (Show only on non-iOS Desktop-like devices) */}
            {showScreenShareButton && ( // <-- شرط جدید اینجا اعمال شده
              <MediaStreamButton
                isStreaming={isScreenCaptureStreaming}
                start={changeStreams('screen')}
                stop={changeStreams('none')}
                onIcon="cancel_presentation"
                offIcon="present_to_all"
                // Disable screen share button also if webcam is active or switching? Your choice.
                // disabled={!connected || isSwitchingCamera || showWebcamAsActive}
                disabled={!connected || isSwitchingCamera } // Kept simpler for now
              />
            )}

            {/* Switch Camera Button */}
            { (isWebcamStableStreaming || isSwitchingCamera) && (
              <button
                className="action-button"
                onClick={rotateWebcam}
                title="Switch camera"
                disabled={!connected || isSwitchingCamera}
              >
                <span className="material-symbols-outlined">switch_camera</span>
              </button>
            )}

            {/* Webcam On/Off Button */}
            <MediaStreamButton
              isStreaming={showWebcamAsActive}
              start={changeStreams('webcam')}
              stop={changeStreams('none')}
              onIcon="videocam_off"
              offIcon="videocam"
              disabled={!connected || isSwitchingCamera}
            />
          </>
        )}
        {children}
      </nav>

      {/* Connection Controls */}
      <div className={cn("connection-container", { connected })}>
        <div className="connection-button-container">
          <button
            ref={connectButtonRef}
            className={cn("action-button connect-toggle", { connected })}
            onClick={async () => {
              if (isSwitchingCamera) return;
              try { if (connected) { await disconnect(); } else { await connect(); } }
              catch (err) { console.error('❌ Connection/Disconnection error:', err); }
            }}
            disabled={isSwitchingCamera}
            title={connected ? "Disconnect Stream" : "Connect Stream"}
          >
            <span className="material-symbols-outlined filled">{connected ? "pause" : "play_arrow"}</span>
          </button>
        </div>
        <span className="text-indicator">{connected ? "Streaming" : "Paused"}</span>
      </div>
    </section>
  );
}

export default memo(ControlTray);