// @ts-nocheck
import { usePolicyStore } from '../../stores/policy';
import { useModelStore } from '../../stores/model';

export const uploadMethods = {
  triggerFileUpload() {
    if (this.uploading) {
      return;
    }
    const input = this.getComposerElement('fileUploadInput');
    if (input) {
      input.click();
    }
  },

  handleFileSelected(files) {
    const policyStore = usePolicyStore();
    if (policyStore.uiBlocks?.block_upload) {
      this.uiPushToast({
        title: '上传被禁用',
        message: '已被管理员禁用上传功能',
        type: 'warning'
      });
      return;
    }
    this.uploadHandleSelected(files);
  },

  normalizeLocalFiles(files) {
    if (!files) return [];
    const list = Array.isArray(files) ? files : Array.from(files);
    return list.filter(Boolean);
  },

  isImageFile(file) {
    const name = file?.name || '';
    const type = file?.type || '';
    return type.startsWith('image/') || /\.(png|jpe?g|webp|gif|bmp|svg)$/i.test(name);
  },

  isVideoFile(file) {
    const name = file?.name || '';
    const type = file?.type || '';
    return type.startsWith('video/') || /\.(mp4|mov|m4v|webm|avi|mkv|flv|mpg|mpeg)$/i.test(name);
  },

  upsertImageEntry(path, filename) {
    if (!path) return;
    const name = filename || path.split('/').pop() || path;
    const list = Array.isArray(this.imageEntries) ? this.imageEntries : [];
    if (list.some((item) => item.path === path)) {
      return;
    }
    this.imageEntries = [{ name, path }, ...list];
  },

  upsertVideoEntry(path, filename) {
    if (!path) return;
    const name = filename || path.split('/').pop() || path;
    const list = Array.isArray(this.videoEntries) ? this.videoEntries : [];
    if (list.some((item) => item.path === path)) {
      return;
    }
    this.videoEntries = [{ name, path }, ...list];
  },

  async handleLocalImageFiles(files) {
    if (!this.isConnected) {
      return;
    }
    if (this.mediaUploading) {
      this.uiPushToast({
        title: '上传中',
        message: '请等待当前图片上传完成',
        type: 'info'
      });
      return;
    }
    const list = this.normalizeLocalFiles(files);
    if (!list.length) {
      return;
    }
    const existingCount = Array.isArray(this.selectedImages) ? this.selectedImages.length : 0;
    const remaining = Math.max(0, 9 - existingCount);
    if (!remaining) {
      this.uiPushToast({
        title: '已达上限',
        message: '最多只能选择 9 张图片',
        type: 'warning'
      });
      return;
    }
    const valid = list.filter((file) => this.isImageFile(file));
    // 兼容 Android WebView 部分机型：返回的 File 可能缺失 type/扩展名，导致识别失败
    // 若来自图片选择器但未识别出有效类型，回退为“按选择结果直接上传”。
    const candidates = valid.length ? valid : list;
    if (valid.length < list.length && valid.length > 0) {
      this.uiPushToast({
        title: '已忽略',
        message: '已跳过非图片文件',
        type: 'info'
      });
    }
    const limited = candidates.slice(0, remaining);
    if (candidates.length > remaining) {
      this.uiPushToast({
        title: '已超出数量',
        message: `最多还能添加 ${remaining} 张图片，已自动截断`,
        type: 'warning'
      });
    }
    const uploaded = await this.uploadBatchFiles(limited, {
      markUploading: true,
      markMediaUploading: true
    });
    if (!uploaded.length) {
      return;
    }
    uploaded.forEach((item) => {
      if (!item?.path) return;
      this.inputAddSelectedImage(item.path);
      this.upsertImageEntry(item.path, item.filename);
    });
    // 上传完成后自动关闭选择窗口
    this.closeImagePicker();
  },

  async handleLocalVideoFiles(files) {
    if (!this.isConnected) {
      return;
    }
    if (this.mediaUploading) {
      this.uiPushToast({
        title: '上传中',
        message: '请等待当前视频上传完成',
        type: 'info'
      });
      return;
    }
    const list = this.normalizeLocalFiles(files);
    if (!list.length) {
      return;
    }
    const valid = list.filter((file) => this.isVideoFile(file));
    // 兼容 Android WebView：文件元数据缺失时回退按选择结果直接上传
    const candidates = valid.length ? valid : list;
    if (valid.length < list.length && valid.length > 0) {
      this.uiPushToast({
        title: '已忽略',
        message: '已跳过非视频文件',
        type: 'info'
      });
    }
    if (candidates.length > 1) {
      this.uiPushToast({
        title: '视频数量过多',
        message: '一次只能选择 1 个视频，已使用第一个',
        type: 'warning'
      });
    }
    const [file] = candidates;
    if (!file) {
      return;
    }
    const uploaded = await this.uploadBatchFiles([file], {
      markUploading: true,
      markMediaUploading: true
    });
    const [item] = uploaded;
    if (!item?.path) {
      return;
    }
    this.inputSetSelectedVideos([item.path]);
    this.inputClearSelectedImages();
    this.upsertVideoEntry(item.path, item.filename);
  },

  async openImagePicker() {
    const modelStore = useModelStore();
    const currentModel = modelStore.models.find((m) => m.key === this.currentModelKey);
    if (!currentModel?.supportsImage) {
      this.uiPushToast({
        title: '当前模型不支持图片',
        message: '请选择支持图片输入的模型后再发送图片',
        type: 'error'
      });
      return;
    }
    this.closeQuickMenu();
    this.inputSetImagePickerOpen(true);
    await this.loadWorkspaceImages();
  },

  closeImagePicker() {
    this.inputSetImagePickerOpen(false);
  },

  async openVideoPicker() {
    const modelStore = useModelStore();
    const currentModel = modelStore.models.find((m) => m.key === this.currentModelKey);
    if (!currentModel?.supportsVideo) {
      this.uiPushToast({
        title: '当前模型不支持视频',
        message: '请切换到支持视频输入的模型后再发送视频',
        type: 'error'
      });
      return;
    }
    this.closeQuickMenu();
    this.inputSetVideoPickerOpen(true);
    await this.loadWorkspaceVideos();
  },

  closeVideoPicker() {
    this.inputSetVideoPickerOpen(false);
  },

  async loadWorkspaceImages() {
    this.imageLoading = true;
    try {
      const entries = await this.fetchAllImageEntries('');
      this.imageEntries = entries;
      if (!entries.length) {
        this.uiPushToast({
          title: '未找到图片',
          message: '工作区内没有可用的图片文件',
          type: 'info'
        });
      }
    } catch (error) {
      console.error('加载图片列表失败', error);
      this.uiPushToast({
        title: '加载图片失败',
        message: error?.message || '请稍后重试',
        type: 'error'
      });
    } finally {
      this.imageLoading = false;
    }
  },

  async fetchAllImageEntries(startPath = '') {
    const queue: string[] = [startPath || ''];
    const visited = new Set<string>();
    const results: Array<{ name: string; path: string }> = [];
    const exts = new Set(['.png', '.jpg', '.jpeg', '.webp', '.gif', '.bmp', '.svg']);
    const maxFolders = 120;

    while (queue.length && visited.size < maxFolders) {
      const path = queue.shift() || '';
      if (visited.has(path)) {
        continue;
      }
      visited.add(path);
      try {
        const resp = await fetch(`/api/gui/files/entries?path=${encodeURIComponent(path)}`, {
          method: 'GET',
          credentials: 'include',
          headers: { Accept: 'application/json' }
        });
        const data = await resp.json().catch(() => null);
        if (!data?.success) {
          continue;
        }
        const items = Array.isArray(data?.data?.items) ? data.data.items : [];
        for (const item of items) {
          const rawPath =
            item?.path ||
            [path, item?.name]
              .filter(Boolean)
              .join('/')
              .replace(/\\/g, '/')
              .replace(/\/{2,}/g, '/');
          const type = String(item?.type || '').toLowerCase();
          if (type === 'directory' || type === 'folder') {
            queue.push(rawPath);
            continue;
          }
          const ext =
            String(item?.extension || '').toLowerCase() ||
            (rawPath.includes('.') ? `.${rawPath.split('.').pop()?.toLowerCase()}` : '');
          if (exts.has(ext)) {
            results.push({
              name: item?.name || rawPath.split('/').pop() || rawPath,
              path: rawPath
            });
            if (results.length >= 400) {
              return results;
            }
          }
        }
      } catch (error) {
        console.warn('遍历文件夹失败', path, error);
      }
    }
    return results;
  },

  async fetchAllVideoEntries(startPath = '') {
    const queue: string[] = [startPath || ''];
    const visited = new Set<string>();
    const results: Array<{ name: string; path: string }> = [];
    const exts = new Set(['.mp4', '.mov', '.mkv', '.avi', '.webm']);
    const maxFolders = 120;

    while (queue.length && visited.size < maxFolders) {
      const path = queue.shift() || '';
      if (visited.has(path)) {
        continue;
      }
      visited.add(path);
      try {
        const resp = await fetch(`/api/gui/files/entries?path=${encodeURIComponent(path)}`, {
          method: 'GET',
          credentials: 'include',
          headers: { Accept: 'application/json' }
        });
        const data = await resp.json().catch(() => null);
        if (!data?.success) {
          continue;
        }
        const items = Array.isArray(data?.data?.items) ? data.data.items : [];
        for (const item of items) {
          const rawPath =
            item?.path ||
            [path, item?.name]
              .filter(Boolean)
              .join('/')
              .replace(/\\/g, '/')
              .replace(/\/{2,}/g, '/');
          const type = String(item?.type || '').toLowerCase();
          if (type === 'directory' || type === 'folder') {
            queue.push(rawPath);
            continue;
          }
          const ext =
            String(item?.extension || '').toLowerCase() ||
            (rawPath.includes('.') ? `.${rawPath.split('.').pop()?.toLowerCase()}` : '');
          if (exts.has(ext)) {
            results.push({
              name: item?.name || rawPath.split('/').pop() || rawPath,
              path: rawPath
            });
            if (results.length >= 200) {
              return results;
            }
          }
        }
      } catch (error) {
        console.warn('遍历文件夹失败', path, error);
      }
    }
    return results;
  },

  async loadWorkspaceVideos() {
    this.videoLoading = true;
    try {
      const entries = await this.fetchAllVideoEntries('');
      this.videoEntries = entries;
      if (!entries.length) {
        this.uiPushToast({
          title: '未找到视频',
          message: '工作区内没有可用的视频文件',
          type: 'info'
        });
      }
    } catch (error) {
      console.error('加载视频列表失败', error);
      this.uiPushToast({
        title: '加载视频失败',
        message: error?.message || '请稍后重试',
        type: 'error'
      });
    } finally {
      this.videoLoading = false;
    }
  },

  handleImagesConfirmed(list) {
    this.inputSetSelectedImages(Array.isArray(list) ? list : []);
    this.inputSetImagePickerOpen(false);
  },
  handleRemoveImage(path) {
    this.inputRemoveSelectedImage(path);
  },
  handleVideosConfirmed(list) {
    const arr = Array.isArray(list) ? list.slice(0, 1) : [];
    this.inputSetSelectedVideos(arr);
    this.inputSetVideoPickerOpen(false);
    if (arr.length) {
      this.inputClearSelectedImages();
    }
  },
  handleRemoveVideo(path) {
    this.inputRemoveSelectedVideo(path);
  },

  handleQuickUpload() {
    if (this.uploading || !this.isConnected) {
      return;
    }
    if (this.isPolicyBlocked('block_upload', '上传功能已被管理员禁用')) {
      return;
    }
    this.triggerFileUpload();
  },

  // 拖拽上传相关方法
  handleDragEnter(event: DragEvent) {
    event.preventDefault();
    event.stopPropagation();
    // 检查是否包含文件
    if (event.dataTransfer?.types?.includes('Files')) {
      this.dragOverActive = true;
    }
  },

  handleDragOver(event: DragEvent) {
    event.preventDefault();
    event.stopPropagation();
  },

  handleDragLeave(event: DragEvent) {
    event.preventDefault();
    event.stopPropagation();
    // 只有当真正离开窗口时才关闭
    const rect = document.body.getBoundingClientRect();
    const x = event.clientX;
    const y = event.clientY;
    if (x <= rect.left || x >= rect.right || y <= rect.top || y >= rect.bottom) {
      this.dragOverActive = false;
    }
  },

  handleDrop(event: DragEvent) {
    event.preventDefault();
    event.stopPropagation();
    this.dragOverActive = false;

    if (!this.isConnected) {
      this.uiPushToast({
        title: '未连接',
        message: '请等待服务器连接后再上传',
        type: 'warning'
      });
      return;
    }

    const policyStore = usePolicyStore();
    if (policyStore.uiBlocks?.block_upload) {
      this.uiPushToast({
        title: '上传被禁用',
        message: '已被管理员禁用上传功能',
        type: 'warning'
      });
      return;
    }

    const files = event.dataTransfer?.files;
    if (!files || files.length === 0) {
      return;
    }

    // 处理拖拽的文件
    this.processDroppedFiles(Array.from(files));
  },

  async processDroppedFiles(files: File[]) {
    if (!files.length) return;

    // 分离图片和非图片文件
    const imageFiles = files.filter(file => this.isImageFile(file));
    const videoFiles = files.filter(file => this.isVideoFile(file));
    const otherFiles = files.filter(file => !this.isImageFile(file) && !this.isVideoFile(file));

    // 优先处理图片，其次视频
    if (imageFiles.length > 0) {
      await this.handleDroppedImages(imageFiles);
    } else if (videoFiles.length > 0) {
      await this.handleDroppedVideo(videoFiles[0]); // 视频只取第一个
    }

    // 处理其他文件（普通文件上传）
    if (otherFiles.length > 0) {
      this.uploadHandleSelected(otherFiles);
    }
  },

  async handleDroppedImages(files: File[]) {
    const modelStore = useModelStore();
    const currentModel = modelStore.models.find((m) => m.key === this.currentModelKey);
    if (!currentModel?.supportsImage) {
      this.uiPushToast({
        title: '当前模型不支持图片',
        message: '请选择支持图片输入的模型后再发送图片',
        type: 'error'
      });
      return;
    }

    // 只上传并添加到输入栏，不自动发送
    await this.handleLocalImageFiles(files);
  },

  async handleDroppedVideo(file: File) {
    const modelStore = useModelStore();
    const currentModel = modelStore.models.find((m) => m.key === this.currentModelKey);
    if (!currentModel?.supportsVideo) {
      this.uiPushToast({
        title: '当前模型不支持视频',
        message: '请切换到支持视频输入的模型后再发送视频',
        type: 'error'
      });
      return;
    }

    // 只上传并添加到输入栏，不自动发送
    await this.handleLocalVideoFiles([file]);
  },

  _boundDragEnter: null as ((e: DragEvent) => void) | null,
  _boundDragOver: null as ((e: DragEvent) => void) | null,
  _boundDragLeave: null as ((e: DragEvent) => void) | null,
  _boundDrop: null as ((e: DragEvent) => void) | null,

  setupDragAndDrop() {
    // 存储绑定后的函数以便后续移除
    this._boundDragEnter = this.handleDragEnter.bind(this);
    this._boundDragOver = this.handleDragOver.bind(this);
    this._boundDragLeave = this.handleDragLeave.bind(this);
    this._boundDrop = this.handleDrop.bind(this);

    // 使用 document.body 作为拖拽监听目标
    document.body.addEventListener('dragenter', this._boundDragEnter);
    document.body.addEventListener('dragover', this._boundDragOver);
    document.body.addEventListener('dragleave', this._boundDragLeave);
    document.body.addEventListener('drop', this._boundDrop);
  },

  teardownDragAndDrop() {
    if (this._boundDragEnter) {
      document.body.removeEventListener('dragenter', this._boundDragEnter);
    }
    if (this._boundDragOver) {
      document.body.removeEventListener('dragover', this._boundDragOver);
    }
    if (this._boundDragLeave) {
      document.body.removeEventListener('dragleave', this._boundDragLeave);
    }
    if (this._boundDrop) {
      document.body.removeEventListener('drop', this._boundDrop);
    }
    this._boundDragEnter = null;
    this._boundDragOver = null;
    this._boundDragLeave = null;
    this._boundDrop = null;
  }
};
