import { BaseBoxShapeUtil, TLBaseShape } from "tldraw"
import { useEffect, useState } from "react"

interface DailyApiResponse {
  url: string;
}

interface DailyRecordingResponse {
  id: string;
}

export type IVideoChatShape = TLBaseShape<
  "VideoChat",
  {
    w: number
    h: number
    roomUrl: string | null
    allowCamera: boolean
    allowMicrophone: boolean
    enableRecording: boolean
    recordingId: string | null // Track active recording
    enableTranscription: boolean
    isTranscribing: boolean
    transcriptionHistory: Array<{
      sender: string
      message: string
      id: string
    }>
    meetingToken: string | null
    isOwner: boolean
  }
>

export class VideoChatShape extends BaseBoxShapeUtil<IVideoChatShape> {
  static override type = "VideoChat"

  indicator(_shape: IVideoChatShape) {
    return null
  }

  getDefaultProps(): IVideoChatShape["props"] {
    const props = {
      roomUrl: null,
      w: 800,
      h: 600,
      allowCamera: false,
      allowMicrophone: false,
      enableRecording: true,
      recordingId: null,
      enableTranscription: true,
      isTranscribing: false,
      transcriptionHistory: [],
      meetingToken: null,
      isOwner: false
    };
    console.log('🔧 getDefaultProps called, returning:', props);
    return props;
  }

  async generateMeetingToken(roomName: string) {
    const workerUrl = import.meta.env.VITE_TLDRAW_WORKER_URL;
    const apiKey = import.meta.env.VITE_DAILY_API_KEY;

    if (!apiKey) {
      throw new Error('Daily.co API key not configured');
    }

    if (!workerUrl) {
      throw new Error('Worker URL is not configured');
    }

    // For now, let's skip token generation and use a simpler approach
    // We'll use the room URL directly and handle owner permissions differently
    console.log('Skipping meeting token generation for now');
    return `token_${roomName}_${Date.now()}`;
  }

  async ensureRoomExists(shape: IVideoChatShape) {
    const boardId = this.editor.getCurrentPageId();
    if (!boardId) {
        throw new Error('Board ID is undefined');
    }

    // Try to get existing room URL from localStorage first
    const storageKey = `videoChat_room_${boardId}`;
    const existingRoomUrl = localStorage.getItem(storageKey);
    const existingToken = localStorage.getItem(`${storageKey}_token`);

    if (existingRoomUrl && existingRoomUrl !== 'undefined' && existingToken) {
        console.log("Using existing room from storage:", existingRoomUrl);
        await this.editor.updateShape<IVideoChatShape>({
            id: shape.id,
            type: shape.type,
            props: {
                ...shape.props,
                roomUrl: existingRoomUrl,
                meetingToken: existingToken,
                isOwner: true, // Assume the creator is the owner
            },
        });
        return;
    }

    if (shape.props.roomUrl !== null && shape.props.roomUrl !== 'undefined' && shape.props.meetingToken) {
        console.log("Room already exists:", shape.props.roomUrl);
        localStorage.setItem(storageKey, shape.props.roomUrl);
        localStorage.setItem(`${storageKey}_token`, shape.props.meetingToken);
        return;
    }

    try {
        const workerUrl = import.meta.env.VITE_TLDRAW_WORKER_URL;
        const apiKey = import.meta.env.VITE_DAILY_API_KEY;

        if (!apiKey) {
            throw new Error('Daily.co API key not configured');
        }

        if (!workerUrl) {
            throw new Error('Worker URL is not configured');
        }

        // Create room name based on board ID and timestamp
        // Sanitize boardId to only use valid Daily.co characters (A-Z, a-z, 0-9, '-', '_')
        const sanitizedBoardId = boardId.replace(/[^A-Za-z0-9\-_]/g, '_');
        const roomName = `board_${sanitizedBoardId}_${Date.now()}`;
        
        console.log('🔧 Room name generation:');
        console.log('Original boardId:', boardId);
        console.log('Sanitized boardId:', sanitizedBoardId);
        console.log('Final roomName:', roomName);

        const response = await fetch(`${workerUrl}/daily/rooms`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${apiKey}`
          },
          body: JSON.stringify({
            name: roomName,
            properties: {
              enable_chat: true,
              enable_screenshare: true,
              start_video_off: true,
              start_audio_off: true
            }
          })
        });

        if (!response.ok) {
          const error = await response.json()
          throw new Error(`Failed to create room (${response.status}): ${JSON.stringify(error)}`)
        }

        const data = (await response.json()) as DailyApiResponse;
        const url = data.url;

        if (!url) throw new Error("Room URL is missing")

        // Generate meeting token for the owner
        // First ensure the room exists, then generate token
        const meetingToken = await this.generateMeetingToken(roomName);

        // Store the room URL and token in localStorage
        localStorage.setItem(storageKey, url);
        localStorage.setItem(`${storageKey}_token`, meetingToken);

        console.log("Room created successfully:", url)
        console.log("Meeting token generated:", meetingToken)
        console.log("Updating shape with new URL and token")
        console.log("Setting isOwner to true")

        await this.editor.updateShape<IVideoChatShape>({
          id: shape.id,
          type: shape.type,
          props: {
            ...shape.props,
            roomUrl: url,
            meetingToken: meetingToken,
            isOwner: true,
          },
        })

        console.log("Shape updated:", this.editor.getShape(shape.id))
        const updatedShape = this.editor.getShape(shape.id) as IVideoChatShape;
        console.log("Updated shape isOwner:", updatedShape?.props.isOwner)
    } catch (error) {
      console.error("Error in ensureRoomExists:", error)
      throw error
    }
  }

  async startRecording(shape: IVideoChatShape) {
    if (!shape.props.roomUrl) return;
    
    const workerUrl = import.meta.env.VITE_TLDRAW_WORKER_URL;
    const apiKey = import.meta.env.VITE_DAILY_API_KEY;

    try {
      // Extract room name from URL (same as transcription methods)
      const roomName = shape.props.roomUrl.split('/').pop();
      if (!roomName) {
        throw new Error('Could not extract room name from URL');
      }

      const response = await fetch(`${workerUrl}/daily/recordings/start`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          room_name: roomName,
          layout: {
            preset: "active-speaker"
          }
        })
      });

      if (!response.ok) throw new Error('Failed to start recording');
      
      const data = await response.json() as DailyRecordingResponse;
      
      await this.editor.updateShape<IVideoChatShape>({
        id: shape.id,
        type: shape.type,
        props: {
          ...shape.props,
          recordingId: data.id
        }
      });

    } catch (error) {
      console.error('Error starting recording:', error);
      throw error;
    }
  }

  async stopRecording(shape: IVideoChatShape) {
    if (!shape.props.recordingId) return;

    const workerUrl = import.meta.env.VITE_TLDRAW_WORKER_URL;
    const apiKey = import.meta.env.VITE_DAILY_API_KEY;

    try {
      await fetch(`${workerUrl}/daily/recordings/${shape.props.recordingId}/stop`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`
        }
      });

      await this.editor.updateShape<IVideoChatShape>({
        id: shape.id,
        type: shape.type,
        props: {
          ...shape.props,
          recordingId: null
        }
      });

    } catch (error) {
      console.error('Error stopping recording:', error);
      throw error;
    }
  }

  async startTranscription(shape: IVideoChatShape) {
    console.log('🎤 startTranscription method called');
    console.log('Shape props:', shape.props);
    console.log('Room URL:', shape.props.roomUrl);
    console.log('Is owner:', shape.props.isOwner);
    
    if (!shape.props.roomUrl || !shape.props.isOwner) {
      console.log('❌ Early return - missing roomUrl or not owner');
      console.log('roomUrl exists:', !!shape.props.roomUrl);
      console.log('isOwner:', shape.props.isOwner);
      return;
    }
    
    try {
      const workerUrl = import.meta.env.VITE_TLDRAW_WORKER_URL;
      const apiKey = import.meta.env.VITE_DAILY_API_KEY;
      
      console.log('🔧 Environment variables:');
      console.log('Worker URL:', workerUrl);
      console.log('API Key exists:', !!apiKey);
      
      // Extract room name from URL
      const roomName = shape.props.roomUrl.split('/').pop();
      console.log('📝 Extracted room name:', roomName);
      
      if (!roomName) {
        throw new Error('Could not extract room name from URL');
      }

      console.log('🌐 Making API request to start transcription...');
      console.log('Request URL:', `${workerUrl}/daily/rooms/${roomName}/start-transcription`);

      const response = await fetch(`${workerUrl}/daily/rooms/${roomName}/start-transcription`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${apiKey}`
        }
      });

      console.log('📡 Response status:', response.status);
      console.log('📡 Response ok:', response.ok);

      if (!response.ok) {
        const error = await response.json();
        console.error('❌ API error response:', error);
        throw new Error(`Failed to start transcription: ${JSON.stringify(error)}`);
      }

      console.log('✅ API call successful, updating shape...');
      await this.editor.updateShape<IVideoChatShape>({
        id: shape.id,
        type: shape.type,
        props: {
          ...shape.props,
          isTranscribing: true,
        }
      });
      console.log('✅ Shape updated with isTranscribing: true');
    } catch (error) {
      console.error('❌ Error starting transcription:', error);
      throw error;
    }
  }

  async stopTranscription(shape: IVideoChatShape) {
    console.log('🛑 stopTranscription method called');
    console.log('Shape props:', shape.props);
    
    if (!shape.props.roomUrl || !shape.props.isOwner) {
      console.log('❌ Early return - missing roomUrl or not owner');
      return;
    }
    
    try {
      const workerUrl = import.meta.env.VITE_TLDRAW_WORKER_URL;
      const apiKey = import.meta.env.VITE_DAILY_API_KEY;
      
      // Extract room name from URL
      const roomName = shape.props.roomUrl.split('/').pop();
      console.log('📝 Extracted room name:', roomName);
      
      if (!roomName) {
        throw new Error('Could not extract room name from URL');
      }

      console.log('🌐 Making API request to stop transcription...');
      const response = await fetch(`${workerUrl}/daily/rooms/${roomName}/stop-transcription`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${apiKey}`
        }
      });

      console.log('📡 Response status:', response.status);

      if (!response.ok) {
        const error = await response.json();
        console.error('❌ API error response:', error);
        throw new Error(`Failed to stop transcription: ${JSON.stringify(error)}`);
      }

      console.log('✅ API call successful, updating shape...');
      await this.editor.updateShape<IVideoChatShape>({
        id: shape.id,
        type: shape.type,
        props: {
          ...shape.props,
          isTranscribing: false,
        }
      });
      console.log('✅ Shape updated with isTranscribing: false');
    } catch (error) {
      console.error('❌ Error stopping transcription:', error);
      throw error;
    }
  }

  addTranscriptionMessage(shape: IVideoChatShape, sender: string, message: string) {
    console.log('📝 addTranscriptionMessage called');
    console.log('Sender:', sender);
    console.log('Message:', message);
    console.log('Current transcription history length:', shape.props.transcriptionHistory.length);
    
    const newMessage = {
      sender,
      message,
      id: `${Date.now()}_${Math.random()}`
    };

    console.log('📝 Adding new message:', newMessage);

    this.editor.updateShape<IVideoChatShape>({
      id: shape.id,
      type: shape.type,
      props: {
        ...shape.props,
        transcriptionHistory: [...shape.props.transcriptionHistory, newMessage]
      }
    });
    
    console.log('✅ Transcription message added to shape');
  }

  component(shape: IVideoChatShape) {
    const [hasPermissions, setHasPermissions] = useState(false)
    const [error, setError] = useState<Error | null>(null)
    const [isLoading, setIsLoading] = useState(true)
    const [roomUrl, setRoomUrl] = useState<string | null>(shape.props.roomUrl)

    useEffect(() => {
        let mounted = true;
        
        const createRoom = async () => {
            try {
                setIsLoading(true);
                await this.ensureRoomExists(shape);
                
                // Get the updated shape after room creation
                const updatedShape = this.editor.getShape(shape.id);
                if (mounted && updatedShape) {
                    setRoomUrl((updatedShape as IVideoChatShape).props.roomUrl);
                }
            } catch (err) {
                if (mounted) {
                    console.error("Error creating room:", err);
                    setError(err as Error);
                }
            } finally {
                if (mounted) {
                    setIsLoading(false);
                }
            }
        };

        createRoom();

        return () => {
            mounted = false;
        };
    }, [shape.id]); // Only re-run if shape.id changes

    useEffect(() => {
      let mounted = true;
      
      const requestPermissions = async () => {
        try {
          if (shape.props.allowCamera || shape.props.allowMicrophone) {
            const constraints = {
              video: shape.props.allowCamera,
              audio: shape.props.allowMicrophone,
            }
            await navigator.mediaDevices.getUserMedia(constraints)
            if (mounted) {
              setHasPermissions(true)
            }
          }
        } catch (err) {
          console.error("Permission request failed:", err)
          if (mounted) {
            setHasPermissions(false)
          }
        }
      }

      requestPermissions()

      return () => {
        mounted = false;
      }
    }, [shape.props.allowCamera, shape.props.allowMicrophone])

    if (error) {
        return <div>Error creating room: {error.message}</div>
    }

    if (isLoading || !roomUrl || roomUrl === 'undefined') {
        return (
            <div
                style={{
                    width: shape.props.w,
                    height: shape.props.h,
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    backgroundColor: "#f0f0f0",
                    borderRadius: "4px",
                }}
            >
                {isLoading ? "Creating room... Please wait" : "Error: No room URL available"}
            </div>
        )
    }

    // Construct URL with permission parameters
    const roomUrlWithParams = new URL(roomUrl)
    roomUrlWithParams.searchParams.set(
      "allow_camera",
      String(shape.props.allowCamera),
    )
    roomUrlWithParams.searchParams.set(
      "allow_mic",
      String(shape.props.allowMicrophone),
    )

    console.log(roomUrl)

    return (
      <div
        style={{
          width: `${shape.props.w}px`,
          height: `${shape.props.h}px`,
          position: "relative",
          pointerEvents: "all",
          overflow: "hidden",
        }}
      >
        <iframe
          src={roomUrlWithParams.toString()}
          width="100%"
          height="100%"
          style={{ 
            border: "none",
            position: "absolute",
            top: 0,
            left: 0,
            right: 0,
            bottom: 0,
          }}
          allow={`camera ${shape.props.allowCamera ? "self" : ""}; microphone ${
            shape.props.allowMicrophone ? "self" : ""
          }`}
        ></iframe>
        
        {/* Recording Button */}
        {shape.props.enableRecording && (
          <button
            onClick={async () => {
              try {
                if (shape.props.recordingId) {
                  await this.stopRecording(shape);
                } else {
                  await this.startRecording(shape);
                }
              } catch (err) {
                console.error('Recording error:', err);
              }
            }}
            style={{
              position: "absolute",
              top: "8px",
              right: "8px",
              padding: "4px 8px",
              background: shape.props.recordingId ? "#ff4444" : "#ffffff",
              border: "1px solid #ccc",
              borderRadius: "4px",
              cursor: "pointer",
              zIndex: 1,
            }}
          >
            {shape.props.recordingId ? "Stop Recording" : "Start Recording"}
          </button>
        )}

        {/* Test Button - Always visible for debugging */}
        <button
          onClick={() => {
            console.log('🧪 Test button clicked!');
            console.log('Shape props:', shape.props);
            alert('Test button clicked! Check console for details.');
          }}
          style={{
            position: "absolute",
            top: "8px",
            left: "8px",
            padding: "4px 8px",
            background: "#ffff00",
            border: "1px solid #000",
            borderRadius: "4px",
            cursor: "pointer",
            zIndex: 1000,
            fontSize: "10px",
          }}
        >
          TEST
        </button>

        {/* Transcription Button - Only for owners */}
        {(() => {
          console.log('🔍 Checking transcription button conditions:');
          console.log('enableTranscription:', shape.props.enableTranscription);
          console.log('isOwner:', shape.props.isOwner);
          console.log('Button should render:', shape.props.enableTranscription && shape.props.isOwner);
          return shape.props.enableTranscription && shape.props.isOwner;
        })() && (
          <button
            onClick={async () => {
              console.log('🚀 Transcription button clicked!');
              console.log('Current transcription state:', shape.props.isTranscribing);
              console.log('Shape props:', shape.props);
              
              try {
                if (shape.props.isTranscribing) {
                  console.log('🛑 Stopping transcription...');
                  await this.stopTranscription(shape);
                  console.log('✅ Transcription stopped successfully');
                } else {
                  console.log('🎤 Starting transcription...');
                  await this.startTranscription(shape);
                  console.log('✅ Transcription started successfully');
                }
              } catch (err) {
                console.error('❌ Transcription error:', err);
              }
            }}
            style={{
              position: "absolute",
              top: "8px",
              right: shape.props.enableRecording ? "120px" : "8px",
              padding: "4px 8px",
              background: shape.props.isTranscribing ? "#44ff44" : "#ffffff",
              border: "1px solid #ccc",
              borderRadius: "4px",
              cursor: "pointer",
              zIndex: 1,
            }}
          >
            {shape.props.isTranscribing ? "Stop Transcription" : "Start Transcription"}
          </button>
        )}

        {/* Transcription History */}
        {shape.props.transcriptionHistory.length > 0 && (
          <div
            style={{
              position: "absolute",
              bottom: "40px",
              left: "8px",
              right: "8px",
              maxHeight: "200px",
              overflowY: "auto",
              background: "rgba(255, 255, 255, 0.95)",
              borderRadius: "4px",
              padding: "8px",
              fontSize: "12px",
              zIndex: 1,
              border: "1px solid #ccc",
            }}
          >
            <div style={{ fontWeight: "bold", marginBottom: "4px" }}>
              Live Transcription:
            </div>
            {shape.props.transcriptionHistory.slice(-10).map((msg) => (
              <div key={msg.id} style={{ marginBottom: "2px" }}>
                <span style={{ fontWeight: "bold", color: "#666" }}>
                  {msg.sender}:
                </span>{" "}
                <span>{msg.message}</span>
              </div>
            ))}
          </div>
        )}

        <p
          style={{
            position: "absolute",
            bottom: 0,
            left: 0,
            margin: "8px",
            padding: "4px 8px",
            background: "rgba(255, 255, 255, 0.9)",
            borderRadius: "4px",
            fontSize: "12px",
            pointerEvents: "all",
            cursor: "text",
            userSelect: "text",
            zIndex: 1,
          }}
        >
          url: {roomUrl}
          {shape.props.isOwner && " (Owner)"}
        </p>
      </div>
    )
  }
}
