import React, { KeyboardEvent, MouseEvent } from 'react';
import { MsgType } from 'matrix-js-sdk';
import { HTMLReactParserOptions } from 'html-react-parser';
import { Opts } from 'linkifyjs';
import { config } from 'folds';
import {
  AudioContent,
  DownloadFile,
  FileContent,
  ImageContent,
  MAudio,
  MBadEncrypted,
  MEmote,
  MFile,
  MImage,
  MLocation,
  MNotice,
  MText,
  MVideo,
  ReadPdfFile,
  ReadTextFile,
  RenderBody,
  ThumbnailContent,
  UnsupportedContent,
  VideoContent,
  VideoFrameThumbnail,
} from './message';
import { UrlPreviewCard, UrlPreviewHolder, YouTubeEmbed, isYouTubeUrl, TikTokEmbed, isTikTokUrl, GiphyEmbed, isGiphyUrl } from './url-preview';
import { Image, MediaControl, Video } from './media';
import { ImageViewer } from './image-viewer';
import { VideoViewer } from './video-viewer';
import { PdfViewer } from './Pdf-viewer';
import { TextViewer } from './text-viewer';
import { testMatrixTo } from '../plugins/matrix-to';
import { IImageContent } from '../../types/matrix/common';
import { filterDisabledUrls } from '../hooks/useRoomEmbedFilters';
import { pluginRegistry } from '../features/settings/plugins/PluginAPI';

type RenderMessageContentProps = {
  displayName: string;
  msgType: string;
  ts: number;
  edited?: boolean;
  getContent: <T>() => T;
  mediaAutoLoad?: boolean;
  urlPreview?: boolean;
  highlightRegex?: RegExp;
  htmlReactParserOptions: HTMLReactParserOptions;
  linkifyOpts: Opts;
  outlineAttachment?: boolean;
  disabledEmbedPatterns?: string[];
  targetEventId?: string;
  onJumboEmojiClick?: (
    targetEventId: string,
    body: string,
    event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>
  ) => void;
};
export function RenderMessageContent({
  displayName,
  msgType,
  ts,
  edited,
  getContent,
  mediaAutoLoad,
  urlPreview,
  highlightRegex,
  htmlReactParserOptions,
  linkifyOpts,
  outlineAttachment,
  disabledEmbedPatterns,
  targetEventId,
  onJumboEmojiClick,
}: RenderMessageContentProps) {
  const renderUrlsPreview = (urls: string[]) => {
    let filteredUrls = urls.filter((url) => !testMatrixTo(url));
    filteredUrls = filterDisabledUrls(filteredUrls, disabledEmbedPatterns ?? []);
    if (filteredUrls.length === 0) return undefined;

    // Separate special URLs from generic ones
    const youtubeUrls = filteredUrls.filter(isYouTubeUrl);
    const tiktokUrls = filteredUrls.filter(isTikTokUrl);
    const giphyUrls = filteredUrls.filter(isGiphyUrl);
    const otherUrls = filteredUrls.filter((url) => !isYouTubeUrl(url) && !isTikTokUrl(url) && !isGiphyUrl(url));

    return (
      <>
        {/* Render YouTube embeds (ad-free via yt-dlp) */}
        {youtubeUrls.map((url) => (
          <YouTubeEmbed key={url} url={url} />
        ))}
        {/* Render TikTok embeds */}
        {tiktokUrls.map((url) => (
          <TikTokEmbed key={url} url={url} />
        ))}
        {/* Render Giphy embeds */}
        {giphyUrls.map((url) => (
          <GiphyEmbed key={url} url={url} />
        ))}
        {/* Render standard URL previews for other links */}
        {otherUrls.length > 0 && (
          <UrlPreviewHolder>
            {otherUrls.map((url) => (
              <UrlPreviewCard key={url} url={url} ts={ts} />
            ))}
          </UrlPreviewHolder>
        )}
      </>
    );
  };
  const handleJumboEmojiClick =
    targetEventId && onJumboEmojiClick
      ? (body: string, event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>) =>
          onJumboEmojiClick(targetEventId, body, event)
      : undefined;
  const renderCaption = () => {
    const content: IImageContent = getContent();
    if (content.filename && content.filename !== content.body) {
      return (
        <MText
          style={{ marginTop: config.space.S200 }}
          edited={edited}
          content={content}
          renderBody={(props) => (
            <RenderBody
              {...props}
              highlightRegex={highlightRegex}
              htmlReactParserOptions={htmlReactParserOptions}
              linkifyOpts={linkifyOpts}
            />
          )}
          renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
        />
      );
    }
    return null;
  };

  const renderFile = () => (
    <>
      <MFile
        content={getContent()}
        renderFileContent={({ body, mimeType, info, encInfo, url }) => (
          <FileContent
            body={body}
            mimeType={mimeType}
            renderAsPdfFile={() => (
              <ReadPdfFile
                body={body}
                mimeType={mimeType}
                url={url}
                encInfo={encInfo}
                renderViewer={(p) => <PdfViewer {...p} />}
              />
            )}
            renderAsTextFile={() => (
              <ReadTextFile
                body={body}
                mimeType={mimeType}
                url={url}
                encInfo={encInfo}
                renderViewer={(p) => <TextViewer {...p} />}
              />
            )}
          >
            <DownloadFile body={body} mimeType={mimeType} url={url} encInfo={encInfo} info={info} />
          </FileContent>
        )}
        outlined={outlineAttachment}
      />
      {renderCaption()}
    </>
  );

  // Check for custom renderer from plugins BEFORE standard type handling
  // so plugins can intercept any msgtype including custom ones.
  const customRendererEarly = pluginRegistry.getRenderer('message');
  if (customRendererEarly) {
    try {
      const messageDataEarly = {
        msgtype: msgType,
        ...getContent(),
      };
      const customContentEarly = customRendererEarly(messageDataEarly, () => null);
      if (customContentEarly) {
        return customContentEarly as React.ReactElement;
      }
    } catch (error) {
      console.error('[RenderMessageContent] Custom renderer error (early):', error);
    }
  }

  if (msgType === MsgType.Text) {
    return (
      <MText
        edited={edited}
        content={getContent()}
        onJumboEmojiClick={handleJumboEmojiClick}
        renderBody={(props) => (
          <RenderBody
            {...props}
            highlightRegex={highlightRegex}
            htmlReactParserOptions={htmlReactParserOptions}
            linkifyOpts={linkifyOpts}
          />
        )}
        renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
      />
    );
  }

  if (msgType === MsgType.Emote) {
    return (
      <MEmote
        displayName={displayName}
        edited={edited}
        content={getContent()}
        onJumboEmojiClick={handleJumboEmojiClick}
        renderBody={(props) => (
          <RenderBody
            {...props}
            highlightRegex={highlightRegex}
            htmlReactParserOptions={htmlReactParserOptions}
            linkifyOpts={linkifyOpts}
          />
        )}
        renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
      />
    );
  }

  if (msgType === MsgType.Notice) {
    return (
      <MNotice
        edited={edited}
        content={getContent()}
        onJumboEmojiClick={handleJumboEmojiClick}
        renderBody={(props) => (
          <RenderBody
            {...props}
            highlightRegex={highlightRegex}
            htmlReactParserOptions={htmlReactParserOptions}
            linkifyOpts={linkifyOpts}
          />
        )}
        renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
      />
    );
  }

  if (msgType === MsgType.Image) {
    return (
      <>
        <MImage
          content={getContent()}
          renderImageContent={(props) => (
            <ImageContent
              {...props}
              autoPlay={mediaAutoLoad}
              renderImage={(p) => <Image {...p} loading="lazy" />}
              renderViewer={(p) => <ImageViewer {...p} />}
            />
          )}
          outlined={outlineAttachment}
        />
        {renderCaption()}
      </>
    );
  }

  if (msgType === MsgType.Video) {
    return (
      <>
        <MVideo
          content={getContent()}
          renderAsFile={renderFile}
          renderVideoContent={({ body, info, mimeType, url, encInfo, ...props }) => {
            const hasValidThumbnail = 
              (typeof info.thumbnail_file?.url === 'string' || typeof info.thumbnail_url === 'string') &&
              typeof info.thumbnail_info?.mimetype === 'string';

            return (
              <VideoContent
                body={body}
                info={info}
                mimeType={mimeType}
                url={url}
                encInfo={encInfo}
                autoPlay={mediaAutoLoad}
                {...props}
                renderThumbnail={
                  mediaAutoLoad
                    ? () => hasValidThumbnail ? (
                        <ThumbnailContent
                          info={info}
                          renderImage={(src) => (
                            <Image alt={body} title={body} src={src} loading="lazy" />
                          )}
                        />
                      ) : (
                        <VideoFrameThumbnail
                          mimeType={mimeType}
                          url={url}
                          encInfo={encInfo}
                          renderImage={(src) => (
                            <Image alt={body} title={body} src={src} loading="lazy" />
                          )}
                        />
                      )
                    : undefined
                }
                renderViewer={(p) => <VideoViewer {...p} />}
                renderVideo={(p) => <Video {...p} />}
              />
            );
          }}
          outlined={outlineAttachment}
        />
        {renderCaption()}
      </>
    );
  }

  if (msgType === MsgType.Audio) {
    return (
      <>
        <MAudio
          content={getContent()}
          renderAsFile={renderFile}
          renderAudioContent={(props) => (
            <AudioContent {...props} renderMediaControl={(p) => <MediaControl {...p} />} />
          )}
          outlined={outlineAttachment}
        />
        {renderCaption()}
      </>
    );
  }

  if (msgType === MsgType.File) {
    return renderFile();
  }

  if (msgType === MsgType.Location) {
    return <MLocation content={getContent()} />;
  }

  if (msgType === 'm.bad.encrypted') {
    return <MBadEncrypted />;
  }

  // Check for custom renderer from plugins FIRST
  const customRenderer = pluginRegistry.getRenderer('message');
  console.log('[RenderMessageContent] customRenderer function:', typeof customRenderer);
  if (customRenderer) {
    try {
      const messageData = {
        msgtype: msgType,
        ...getContent(),
      };
      console.log('[RenderMessageContent] Calling customRenderer with msgtype:', msgType);
      console.log('[RenderMessageContent] messageData:', messageData);
      const customContent = customRenderer(
        messageData,
        () => {
          console.log('[RenderMessageContent] defaultRenderer called');
          return null;
        }
      );
      console.log('[RenderMessageContent] customRenderer returned:', customContent);
      console.log('[RenderMessageContent] customContent type:', typeof customContent);
      if (customContent) {
        console.log('[RenderMessageContent] Returning custom content');
        return customContent as React.ReactElement;
      }
    } catch (error) {
      console.error('[RenderMessageContent] Custom renderer error:', error);
    }
  } else {
    console.log('[RenderMessageContent] No custom renderer registered');
  }

  return <UnsupportedContent />;
}
