import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
import Hls from 'hls.js';
import axios from 'axios';
import { container, CoreEnv } from '@roasmax/core';
import { snowflake } from '@roasmax/utils';
import { useQuery } from '@tanstack/react-query';
import { LocAttachmentController } from '@roasmax/sdk';

export interface OnSourceLoaded {
  (player: HTMLVideoElement | null): void;
}
export interface OnPlayerError {
  (err: Error, player: HTMLVideoElement | null): void;
}
export interface OnPlayerTimeChange {
  (player: HTMLVideoElement | null): void;
}
export interface LiveStreamPlayerRef {
  seek(time: number): void;
  pause(): void;
  play(): void;
  getCurrentTime(): number;
  isPaused(): boolean;
  getDuration(): number;
  captureFrame(): string | undefined;
  fullScreen(): void;
}

export async function uploadCaptureFrame(content: string, projectId: string): Promise<{ urn: string }> {
  const coreEnv = container.resolve(CoreEnv);
  return axios
    .create({
      baseURL: coreEnv.MODAL_BASE_URL,
      headers: {
        Authorization: `Bearer ${coreEnv.MODAL_SERVER_KEY || 'bowong7777'}`,
      },
    })
    .request({
      url: `/cache/upload-s3-b64`,
      method: `post`,
      data: {
        file: {
          raw_content: content,
          filename: `images/${projectId}/${snowflake.nextId()}.png`,
          content_type: `application/json`,
        },
      },
    })
    .then((res) => res.data);
}

export const LiveStreamPlayer: React.FC<{
  id?: string;
  ref?: React.RefObject<LiveStreamPlayerRef | null>;
  onSourceLoaded: OnSourceLoaded;
  onError: OnPlayerError;
  onTimeChange: OnPlayerTimeChange;
}> = ({ id, onSourceLoaded, onError, onTimeChange, ref }) => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const hlsRef = useRef<Hls | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  const { data: attachment } = useQuery({
    queryKey: [`generateUrlById`, id],
    queryFn: async () => {
      if (!id) return ``;
      const c = container.resolve(LocAttachmentController);
      const attachment = await c.get(id);
      return attachment;
    },
  });

  useImperativeHandle(ref, () => ({
    seek: (time: number) => {
      videoRef.current && (videoRef.current.currentTime = time);
    },
    pause: () => {
      videoRef.current?.pause();
    },
    play: () => {
      videoRef.current?.play();
    },
    isPaused: () => {
      return !!videoRef.current?.paused;
    },
    getCurrentTime: () => {
      return videoRef.current?.currentTime || 0;
    },
    getDuration: () => {
      return videoRef.current?.duration || 0;
    },
    captureFrame: () => {
      const video = videoRef.current;
      if (!video) return;
      // 创建canvas元素
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      if (!ctx) return;
      // 设置canvas尺寸
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;

      // 上传到modal
      // 绘制视频帧到canvas
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      const dataURL = canvas.toDataURL('image/jpeg', 0.05);
      return dataURL;
    },
    fullScreen: () => {
      const video = videoRef.current;
      if (video) {
        video.requestFullscreen();
      }
    },
  }));

  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;

    const showLoading = () => setIsLoading(true);
    const hideLoading = () => setIsLoading(false);

    video.addEventListener('waiting', showLoading);
    video.addEventListener('seeking', showLoading);

    video.addEventListener('playing', hideLoading);
    video.addEventListener('seeked', hideLoading);
    video.addEventListener('canplay', hideLoading);

    return () => {
      if (!video) return;
      video.removeEventListener('waiting', showLoading);
      video.removeEventListener('seeking', showLoading);
      video.removeEventListener('playing', hideLoading);
      video.removeEventListener('seeked', hideLoading);
      video.removeEventListener('canplay', hideLoading);
    };
  }, []);

  useEffect(() => {
    const video = videoRef.current;
    if (!video || !attachment) return;

    if (hlsRef.current) {
      hlsRef.current.destroy();
      hlsRef.current = null;
    }

    video.addEventListener('loadedmetadata', (a) => {
      return onSourceLoaded(video);
    });
    video.addEventListener('timeupdate', () => onTimeChange(video));
    video.addEventListener('error', () => onError(new Error('Video error'), video));
    if (attachment.type === 'live-stream') {
      if (video.canPlayType('application/vnd.apple.mpegurl')) {
        // Safari等原生支持HLS
        video.src = attachment.url!;
        video.poster = attachment.coverUrl!;
      } else if (Hls.isSupported()) {
        // 其他浏览器用hls.js
        video.poster = attachment.coverUrl!;
        const hls = new Hls();
        hlsRef.current = hls;
        // attachment.url!
        console.log(attachment.url);
        hls.loadSource(attachment.url!);
        hls.attachMedia(video);
        hls.on(Hls.Events.ERROR, (event, data) => {
          if (data.details === Hls.ErrorDetails.MANIFEST_LOAD_ERROR) {
            const corsError = new Error('CORS error: Check server Access-Control-Allow-Origin headers');
            onError(corsError, video);
          } else {
            onError(new Error(data?.details || 'HLS.js error'), video);
          }
        });
      } else {
        onError(new Error('HLS is not supported in this browser'), video);
      }
    } else {
      video.src = attachment.url!;
      video.poster = attachment.coverUrl!;
    }
    return () => {
      if (hlsRef.current) {
        hlsRef.current.destroy();
        hlsRef.current = null;
      }
      if (video) {
        video.src = '';
      }
    };
  }, [attachment]);

  return (
    <div className="relative h-full w-full">
      <video ref={videoRef} crossOrigin="anonymous" className="h-full w-full bg-[#18181A]" autoPlay preload="auto" />
      {isLoading && (
        <div className="absolute inset-0 flex items-center justify-center">
          <div className="h-12 w-12 animate-spin rounded-full border-4 border-solid border-white border-t-transparent" />
        </div>
      )}
    </div>
  );
};
