import React, { useEffect, useRef, useState } from 'react';
import { Box, Icon, Icons, Text, color } from 'folds';
import { Room } from 'matrix-js-sdk';
import { ClientWidgetApi, Widget } from 'matrix-widget-api';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { GeneralWidgetDriver } from './GeneralWidgetDriver';
import { isWidgetUrlSafe } from './widgetUtils';

type RoomWidgetViewProps = {
  room: Room;
  widget: Widget;
};

// Hosts one room widget in a sandboxed iframe via ClientWidgetApi (so widgets
// that wait on the client handshake load), with a conservative capability driver.
// Re-mounts only when the widget id or its (template) URL changes — not on every
// unrelated room-state update — so viewing a widget doesn't reload constantly.
export function RoomWidgetView({ room, widget }: RoomWidgetViewProps) {
  const mx = useMatrixClient();
  const containerRef = useRef<HTMLDivElement>(null);
  const widgetRef = useRef(widget);
  widgetRef.current = widget;
  const [blocked, setBlocked] = useState(false);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return undefined;
    const current = widgetRef.current;

    const completeUrl = current.getCompleteUrl({
      currentUserId: mx.getSafeUserId(),
      widgetRoomId: room.roomId,
      deviceId: mx.getDeviceId() ?? undefined,
      baseUrl: mx.baseUrl,
    });

    // Security: never render a same-origin widget with allow-same-origin (a
    // same-origin frame could break out of the sandbox against our own origin).
    if (!isWidgetUrlSafe(completeUrl, window.location.origin)) {
      setBlocked(true);
      return undefined;
    }
    setBlocked(false);

    const iframe = document.createElement('iframe');
    iframe.title = current.name || 'Widget';
    iframe.sandbox.value =
      'allow-forms allow-scripts allow-same-origin allow-popups allow-downloads';
    iframe.allow = 'autoplay; clipboard-write;';
    iframe.src = completeUrl;
    iframe.style.width = '100%';
    iframe.style.height = '100%';
    iframe.style.border = 'none';
    container.append(iframe);

    const clientApi = new ClientWidgetApi(current, iframe, new GeneralWidgetDriver());
    clientApi.setViewedRoomId(room.roomId);

    return () => {
      clientApi.stop();
      iframe.remove();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mx, room.roomId, widget.id, widget.templateUrl]);

  if (blocked) {
    return (
      <Box direction="Column" grow="Yes" alignItems="Center" justifyContent="Center" gap="200">
        <Icon size="400" src={Icons.Warning} style={{ color: color.Warning.Main }} />
        <Text size="T300" align="Center">
          This widget can&apos;t be loaded because its URL is on this app&apos;s own origin.
        </Text>
      </Box>
    );
  }

  return <Box ref={containerRef} grow="Yes" style={{ height: '100%', minHeight: 0 }} />;
}
