import { useState, useCallback, useEffect, useRef } from "react";
import {
  VideoSegmentEditUseCase,
} from "../usecase/ShotEditUsecase";
import {
  MatchedPerson,
  RoleRecognitionResponse
} from "@/api/DTO/movieEdit";
import { ScriptRoleEntity, VideoSegmentEntity } from "../domain/Entities";
import { LensType, SimpleCharacter } from "../domain/valueObject";
import { getUploadToken, uploadToQiniu } from "@/api/common";
import { SaveEditUseCase } from "../usecase/SaveEditUseCase";
import { getNewShotVideo } from "@/api/video_flow";

/**
 * 视频片段服务Hook接口
 * 定义视频片段服务Hook的所有状态和操作方法
 */
export interface UseShotService {
  // 响应式状态
  /** 加载状态 */
  loading: boolean;
  /** 视频片段列表 */
  videoSegments: VideoSegmentEntity[];
  /** 剧本中角色列表 */
  scriptRoles: ScriptRoleEntity[];
  /** 当前选中的视频片段 */
  selectedSegment: VideoSegmentEntity | null;
  /** 识别出的人物信息 */
  matched_persons: MatchedPerson[];
  // 操作方法
  /** 获取视频片段列表 */
  getVideoSegmentList: (projectId: string) => Promise<void>;
  /** 重新生成视频片段 */
  regenerateVideoSegment: () => Promise<VideoSegmentEntity>;
  /** AI优化视频内容 */
  optimizeVideoContent: (
    shotId: string,
    userRequirement: string,
    lensData: LensType[]
  ) => Promise<LensType[]>;
  /** 中断当前操作 */
  abortOperation: () => void;
  /** 设置选中的视频片段 */
  setSelectedSegment: (segment: VideoSegmentEntity | null) => void;
  /** 添加新镜头到选中的视频片段 */
  addNewLens: () => void;
  /** 删除指定镜头 */
  deleteLens: (lensName: string) => void;
  /** 获取视频当前帧并上传到七牛云 */
  filterRole: (
    video: HTMLVideoElement
  ) => Promise<RoleRecognitionResponse | undefined>;
  /** 设置角色简单数据 */
  setSimpleCharacter: (characters: SimpleCharacter[]) => void;
  /** 计算识别框 */
  calculateRecognitionBoxes: (containerElement: HTMLElement, matched_persons: MatchedPerson[]) => Array<{
    left: number;
    top: number;
    width: number;
    height: number;
    person_id: string;
  }>;
}

/**
 * 视频片段服务Hook
 * 提供视频片段相关的所有状态管理和操作方法
 * 包括获取视频列表、重新生成视频、AI优化等功能
 */
export const useShotService = (): UseShotService => {
  // 响应式状态
  const [loading, setLoading] = useState<boolean>(false);
  const [videoSegments, setVideoSegments] = useState<VideoSegmentEntity[]>([]);
  const [scriptRoles, setScriptRoles] = useState<ScriptRoleEntity[]>([]);
  const [selectedSegment, setSelectedSegment] =
    useState<VideoSegmentEntity | null>(null);
  const [projectId, setProjectId] = useState<string>("");
  const [simpleCharacter, setSimpleCharacter] = useState<SimpleCharacter[]>([]);
  const [matched_persons, setMatched_persons] = useState<MatchedPerson[]>([]);
  // 轮询任务ID
  const [intervalId, setIntervalId] = useState<NodeJS.Timeout | null>(null);
  // UseCase实例
  const [vidoEditUseCase] = useState<VideoSegmentEditUseCase>(
    new VideoSegmentEditUseCase()
  );
  const [generateTaskIds, setGenerateTaskIds] = useState<Set<string>>(new Set());
  /**
   * 获取视频片段列表
   * @param projectId 项目ID
   */
  const getVideoSegmentList = useCallback(
    async (projectId: string): Promise<void> => {
      try {
        setLoading(true);

        const { segments, roles } = await vidoEditUseCase.getVideoSegmentList(projectId);
        setProjectId(projectId);
        setVideoSegments(segments);
        setScriptRoles(roles);
      } catch (error) {
        console.error("获取视频片段列表失败:", error);
      } finally {
        setLoading(false);
      }
    },
    [vidoEditUseCase]
  );

  // 组件卸载时清理定时器
  useEffect(() => {
    return () => {
      if (intervalId) {
        clearInterval(intervalId);
        setIntervalId(null);
      }
    };
  }, [intervalId]);

  /**
   * 轮询获取视频生成状态
   * @param taskId - 任务ID
   * @returns Promise<void>
   */
  // 使用 ref 来跟踪组件是否已卸载
  const isComponentMounted = useRef(true);
  
  // 在组件挂载时设置为 true，卸载时设置为 false
  useEffect(() => {
    isComponentMounted.current = true;
    
    return () => {
      isComponentMounted.current = false;
    };
  }, []);

  const pollVideoStatus = useCallback(async (taskId: string): Promise<void> => {
    const maxAttempts = 60; // 最大轮询次数
    const interval = 10000; // 轮询间隔时间（毫秒）
    let attempts = 0;
    let timeoutId: NodeJS.Timeout;

    const poll = async (): Promise<void> => {
      
      // 如果组件已卸载，停止轮询
      if (!isComponentMounted.current) {
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
        return;
      }
      try {
        const result = await getNewShotVideo({ task_id: taskId });
        
        if (!result?.data) {
          // 更新 selectedSegment
          setSelectedSegment(prev => ({
            ...prev!,
            videoUrl: [],
            video_status: 2 // 设置为失败状态
          }));

          // 同步更新 videoSegments 中的对应项
          setVideoSegments(prev => 
            prev.map(segment => 
              segment.id === selectedSegment!.id
                ? {
                    ...segment,
                    videoUrl: [],
                    video_status: 2,
                    status: 2 // 更新片段状态为失败
                  }
                : segment
            )
          );
        }

        const { status, urls, message } = result.data;

        // 如果任务完成或失败，更新视频片段数据
        if (status === 'COMPLETED' || status === 'FAILED') {
            if (selectedSegment && status === 'COMPLETED' && urls?.length > 0) {
              // 更新 selectedSegment
              const updatedVideos = urls.map((url: string) => ({
                video_url: url,
                video_id: selectedSegment!.id,
                video_status: 1
              }));

              
              setSelectedSegment(prev => ({
                ...prev!,
                videoUrl: updatedVideos,
                video_status: 1 // 设置为已完成状态
              }));

              // 同步更新 videoSegments 中的对应项
              setVideoSegments(prev => 
                prev.map(segment => 
                  segment.id === selectedSegment.id
                    ? {
                        ...segment,
                        videoUrl: updatedVideos,
                        video_status: 1,
                        status: 1 // 更新片段状态为完成
                      }
                    : segment
                )
              );
              
            } else {
              
              // 更新 selectedSegment
              setSelectedSegment(prev => ({
                ...prev!,
                videoUrl: [],
                video_status: 2 // 设置为失败状态
              }));

              // 同步更新 videoSegments 中的对应项
              setVideoSegments(prev => 
                prev.map(segment => 
                  segment.id === selectedSegment!.id
                    ? {
                        ...segment,
                        videoUrl: [],
                        video_status: 2,
                        status: 2 // 更新片段状态为失败
                      }
                    : segment
                )
              );
              
          }
          return;
        }

        // 如果未完成且未达到最大尝试次数，继续轮询
        if (attempts < maxAttempts && isComponentMounted.current) {
          attempts++;
          timeoutId = setTimeout(poll, interval);
        } else {
          setSelectedSegment(prev => ({
            ...prev!,
            video_status: 2 // 设置为失败状态
          }));
        }
      } catch (error) {
        setSelectedSegment(prev => ({
          ...prev!,
          video_status: 2 // 设置为失败状态
        }));
      }
    };

    await poll();
  }, [selectedSegment]);

  /**
   * 重新生成视频片段
   * @param shotPrompt 镜头描述数据
   * @param shotId 视频片段ID（可选）
   * @param roleReplaceParams 角色替换参数（可选）
   * @param sceneReplaceParams 场景替换参数（可选）
   * @returns Promise<VideoSegmentEntity> 重新生成的视频片段
   */
  const regenerateVideoSegment =
    useCallback(async (): Promise<VideoSegmentEntity> => {
      try {
        setLoading(true);

        // 调用API重新生成视频片段，返回任务状态信息
        const taskResult = await vidoEditUseCase.regenerateVideoSegment(
          projectId,
          selectedSegment!.lens,
          selectedSegment!.id
        );

        // 保存任务ID用于后续状态查询
        setGenerateTaskIds(prev => prev.add(taskResult.task_id));
        SaveEditUseCase.setVideoTasks([
          ...SaveEditUseCase.videoTasks,
          {
            task_id: taskResult.task_id,
            video_ids: [selectedSegment!.id],
          },
        ]);

        // 如果重新生成的是现有片段，更新其状态为处理中 (0: 视频加载中)
        if (selectedSegment) {
          setVideoSegments((prev) =>
            prev.map((segment) =>
              segment.id === selectedSegment.id
                ? {
                    ...segment,
                    videoUrl: [],
                    video_status: 0,
                    status: 0, // 设置为视频加载中状态
                  }
                : segment
            )
          );

          // 开始轮询视频生成状态
          await pollVideoStatus(taskResult.task_id);
        }

        return selectedSegment!;
      } catch (error) {
        console.error("重新生成视频片段失败:", error);
        throw error;
      } finally {
        setLoading(false);
      }
    }, [projectId, selectedSegment, vidoEditUseCase, pollVideoStatus]);

  /**
   * AI优化视频内容
   * @param shotId 视频片段ID
   * @param userRequirement 用户优化需求
   * @param lensData 镜头数据数组
   * @returns Promise<LensType[]> 优化后的镜头数据
   */
  const optimizeVideoContent = useCallback(
    async (
      shotId: string,
      userRequirement: string,
      lensData: LensType[]
    ): Promise<LensType[]> => {
      try {
        setLoading(true);

        const optimizedLensData = await vidoEditUseCase.optimizeVideoContent(
          shotId,
          userRequirement,
          lensData
        );

        // 注意：这里不再更新videoSegments状态，因为返回的是LensType[]而不是VideoSegmentEntity
        // 调用者需要自己处理优化后的镜头数据

        return optimizedLensData;
      } catch (error) {
        console.error("AI优化视频内容失败:", error);
        throw error;
      } finally {
        setLoading(false);
      }
    },
    [vidoEditUseCase]
  );
  /**
   * 中断当前操作
   */
  const abortOperation = useCallback((): void => {
    // vidoEditUseCase.abortOperation();
    setLoading(false);
  }, []);

  /**
   * 设置选中的视频片段
   */
  const setSelectedSegmentHandler = useCallback(
    (segment: VideoSegmentEntity | null): void => {
      setSelectedSegment(segment);
    },
    []
  );

  /**
   * 添加新镜头到选中的视频片段
   * @description 在selectedSegment的lens数组中添加一个新的空镜头，镜头名称按顺序命名
   */
  const addNewLens = useCallback((): void => {
    if (!selectedSegment) {
      console.warn("没有选中的视频片段，无法添加镜头");
      return;
    }

    // 计算下一个镜头编号
    const currentLensCount = selectedSegment.lens.length;
    const newLensName = `镜头${currentLensCount + 1}`;

    // 创建新的空镜头
    const newLens = new LensType(newLensName, "", []);

    // 创建更新后的片段
    const updatedSegment: VideoSegmentEntity = {
      ...selectedSegment,
      lens: [...selectedSegment.lens, newLens],
    };

    // 批量更新状态，避免多次重渲染
    setSelectedSegment(updatedSegment);
    setVideoSegments((prev) => {
      const segmentIndex = prev.findIndex(
        (segment) => segment.id === selectedSegment.id
      );
      if (segmentIndex === -1) return prev;

      const newSegments = [...prev];
      newSegments[segmentIndex] = updatedSegment;
      return newSegments;
    });
  }, [selectedSegment]);

  /**
   * 删除指定镜头
   * @param lensName 要删除的镜头名称
   */
  const deleteLens = useCallback(
    (lensName: string): void => {
      if (!selectedSegment) {
        console.warn("没有选中的视频片段，无法删除镜头");
        return;
      }

      // 过滤掉指定名称的镜头并重新排序
      const updatedLens = selectedSegment.lens
        .filter((lens) => lens.name !== lensName)
        .map(
          (lens, index) =>
            new LensType(`镜头${index + 1}`, lens.script, lens.content)
        );

      // 创建更新后的片段
      const updatedSegment: VideoSegmentEntity = {
        ...selectedSegment,
        lens: updatedLens,
      };

      // 批量更新状态，避免多次重渲染
      setSelectedSegment(updatedSegment);
      setVideoSegments((prev) => {
        const segmentIndex = prev.findIndex(
          (segment) => segment.id === selectedSegment.id
        );
        if (segmentIndex === -1) return prev;

        const newSegments = [...prev];
        newSegments[segmentIndex] = updatedSegment;
        return newSegments;
      });
    },
    [selectedSegment]
  );

  /**
   * 获取视频当前帧的画面，上传到七牛云，并返回七牛云的图片地址,然后调用接口识别出里面的人物信息，返回人物信息
   * @param video HTML视频元素
   * @param projectId 项目ID
   * @param videoId 视频ID
   * @returns Promise<string> 七牛云的图片地址
   */
  const filterRole = useCallback(
    async (video: HTMLVideoElement) => {
      try {
        // 创建canvas元素来截取视频帧
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        console.log(video);
        video.crossOrigin = "anonymous";
        if (!ctx) {
          throw new Error("无法获取canvas上下文");
        }

        // 设置canvas尺寸为视频尺寸
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;

        // 将当前视频帧绘制到canvas上
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

        // 将canvas转换为blob
        const blob = await new Promise<Blob>((resolve, reject) => {
          canvas.toBlob((blob) => {
            if (blob) {
              resolve(blob);
            } else {
              reject(new Error("无法将canvas转换为blob"));
            }
          }, "image/png");
        });

        // 创建File对象
        const file = new File([blob], `frame_${Date.now()}.png`, {
          type: "image/png",
        });

        // 获取上传token
        const { token } = await getUploadToken();

        // 上传到七牛云
        const imageUrl = await uploadToQiniu(file, token);
        // 调用用例中的识别角色方法
        try {
          const recognitionResult =
            await vidoEditUseCase.recognizeRoleFromImage(
              projectId,
              selectedSegment!.id,
              imageUrl
            );
          console.log("角色识别结果:", recognitionResult);
          setMatched_persons(
            recognitionResult.recognition_result.data
          );
          return recognitionResult;
        } catch (recognitionError) {
          console.warn("角色识别失败，但图片上传成功:", recognitionError);
        }
      } catch (error) {
        console.error("获取视频帧失败:", error);
        throw error;
      }
    },
    [projectId, selectedSegment, vidoEditUseCase]
  );

   /**
   * 计算识别框的属性
   * @description 根据DOM元素尺寸和匹配数据计算识别框的位置和尺寸
   * @param containerElement DOM容器元素
   * @returns 计算后的识别框属性数组
   */
   const calculateRecognitionBoxes = (
    containerElement: HTMLElement,
    matched_persons: MatchedPerson[] = []
  ): Array<{
    /** 横向定位坐标 */
    left: number;
    /** 纵向定位坐标 */
    top: number;
    /** 宽度 */
    width: number;
    /** 高度 */
    height: number;
    /** 人物ID */
    person_id: string;
  }> => {
    // 获取容器元素的尺寸
    const containerRect = containerElement.getBoundingClientRect();
    const containerWidth = containerRect.width;
    const containerHeight = containerRect.height;

    // 计算识别框属性
    return matched_persons
      .map((person) => {

        // 计算绝对坐标和尺寸（百分比转像素）
        const left = Number((person.x || 0).toFixed(4)) * containerWidth;
        const top = Number((person.y || 0).toFixed(4)) * containerHeight;
        const width = Number((person.width || 0).toFixed(4)) * containerWidth;
        const height = Number((person.height || 0).toFixed(4)) * containerHeight;
        console.log('left-top-width-height', left, top, width, height);
        return {
          left,
          top,
          width,
          height,
          person_id: person.person_id
        };
      })
      .filter(Boolean) as Array<{
        left: number;
        top: number;
        width: number;
        height: number;
        person_id: string;
      }>;
  };
  return {
    // 响应式状态
    loading,
    videoSegments,
    scriptRoles,
    selectedSegment,
    matched_persons,
    // 操作方法
    getVideoSegmentList,
    regenerateVideoSegment,
    optimizeVideoContent,
    abortOperation,
    setSelectedSegment: setSelectedSegmentHandler,
    addNewLens,
    deleteLens,
    filterRole,
    setSimpleCharacter,
    calculateRecognitionBoxes
  };
};
