import request from '@/utils/request';
import CryptoJS from 'crypto-js';

/**
 * WPS 三阶段保存接口实现
 *
 * 注意：当前实现包含前端模拟版本，用于开发和测试
 * 生产环境应该使用真实的后端接口
 */

// 是否使用前端模拟（开发模式）
const USE_MOCK = true; // 设置为 false 使用真实后端接口

// 文档信息接口
export interface FileInfo {
  id: string;
  name: string;
  version: number;
  size: number;
  create_time: number;
  modify_time: number;
  creator_id: string;
  modifier_id: string;
}

// 准备上传参数
export interface PrepareUploadParams {
  file_id: string;
}

// 准备上传返回
export interface PrepareUploadResponse {
  digest_types: string[];
}

// 获取上传地址参数
export interface GetUploadAddressParams {
  file_id: string;
  name: string;
  size: number;
  digest: Record<string, string>;
  is_manual: boolean;
  attachment_size?: number;
  content_type?: string;
}

// 获取上传地址返回
export interface GetUploadAddressResponse {
  url: string;
  method: string;
  headers?: Record<string, string>;
  params?: Record<string, string>;
  send_back_params?: Record<string, string>;
}

// 上传完成参数
export interface UploadCompleteParams {
  file_id: string;
  request: GetUploadAddressParams;
  response: {
    status_code: number;
    headers?: Record<string, string>;
    body?: string; // base64 编码
  };
  send_back_params?: Record<string, string>;
}

/**
 * 第一阶段：准备上传
 * 协商摘要算法
 */
export const prepareUpload = (params: PrepareUploadParams): Promise<PrepareUploadResponse> => {
  if (USE_MOCK) {
    // 前端模拟实现
    return Promise.resolve({
      digest_types: ['sha1', 'md5', 'sha256']
    });
  }

  return request({
    url: `/v3/3rd/files/${params.file_id}/upload/prepare`,
    method: 'get'
  });
};

/**
 * 第二阶段：获取上传地址
 * 获取文件上传的目标地址
 */
export const getUploadAddress = (params: GetUploadAddressParams): Promise<GetUploadAddressResponse> => {
  if (USE_MOCK) {
    // 前端模拟实现 - 使用 Blob URL
    return Promise.resolve({
      url: 'mock://upload', // 模拟上传地址
      method: 'PUT',
      headers: {},
      params: {},
      send_back_params: {
        file_id: params.file_id,
        timestamp: Date.now().toString()
      }
    });
  }

  return request({
    url: `/v3/3rd/files/${params.file_id}/upload/address`,
    method: 'post',
    data: {
      name: params.name,
      size: params.size,
      digest: params.digest,
      is_manual: params.is_manual,
      attachment_size: params.attachment_size,
      content_type: params.content_type
    }
  });
};

/**
 * 第三阶段：上传完成通知
 * 通知接入方上传已完成
 */
export const uploadComplete = (params: UploadCompleteParams): Promise<FileInfo> => {
  if (USE_MOCK) {
    // 前端模拟实现 - 使用 localStorage 存储文件信息
    const fileId = params.file_id;
    const currentTime = Math.floor(Date.now() / 1000);

    // 从 localStorage 获取或创建文件记录
    const storageKey = `wps_file_${fileId}`;
    let fileRecord: any = null;

    try {
      const stored = localStorage.getItem(storageKey);
      if (stored) {
        fileRecord = JSON.parse(stored);
      }
    } catch (err) {
      console.warn('读取文件记录失败:', err);
    }

    // 创建或更新文件信息
    const version = fileRecord ? fileRecord.version + 1 : 1;
    const fileInfo: FileInfo = {
      id: fileId,
      name: params.request.name,
      version: version,
      size: params.request.size,
      create_time: fileRecord ? fileRecord.create_time : currentTime,
      modify_time: currentTime,
      creator_id: fileRecord ? fileRecord.creator_id : 'user_' + Date.now(),
      modifier_id: 'user_' + Date.now()
    };

    // 保存到 localStorage
    try {
      localStorage.setItem(storageKey, JSON.stringify(fileInfo));
      console.log('[前端模拟] 文件信息已保存到 localStorage:', fileInfo);
    } catch (err) {
      console.error('[前端模拟] 保存文件信息失败:', err);
    }

    return Promise.resolve(fileInfo);
  }

  return request({
    url: `/v3/3rd/files/${params.file_id}/upload/complete`,
    method: 'post',
    data: {
      request: params.request,
      response: params.response,
      send_back_params: params.send_back_params
    }
  });
};

/**
 * 计算文件摘要
 * @param file 文件 Blob 或 ArrayBuffer
 * @param algorithm 算法类型 md5/sha1/sha256
 */
export const calculateDigest = async (file: Blob | ArrayBuffer, algorithm: 'md5' | 'sha1' | 'sha256'): Promise<string> => {
  let arrayBuffer: ArrayBuffer;

  if (file instanceof Blob) {
    arrayBuffer = await file.arrayBuffer();
  } else {
    arrayBuffer = file;
  }

  // 转换为 WordArray
  const wordArray = CryptoJS.lib.WordArray.create(arrayBuffer as any);

  // 计算摘要
  let hash: any;
  switch (algorithm) {
    case 'md5':
      hash = CryptoJS.MD5(wordArray);
      break;
    case 'sha1':
      hash = CryptoJS.SHA1(wordArray);
      break;
    case 'sha256':
      hash = CryptoJS.SHA256(wordArray);
      break;
    default:
      throw new Error(`不支持的算法: ${algorithm}`);
  }

  return hash.toString();
};

/**
 * 完整的三阶段保存流程
 * @param fileId 文件ID
 * @param fileName 文件名
 * @param fileBlob 文件内容
 * @param isManual 是否手动保存
 */
export const saveFileThreePhase = async (fileId: string, fileName: string, fileBlob: Blob, isManual: boolean = false): Promise<FileInfo> => {
  try {
    // 第一阶段：准备上传，协商摘要算法
    console.log('[WPS保存] 第一阶段：准备上传');
    const prepareResult = await prepareUpload({ file_id: fileId });
    const digestTypes = prepareResult.digest_types || ['sha1'];
    console.log('[WPS保存] 支持的摘要算法:', digestTypes);

    // 计算文件摘要
    console.log('[WPS保存] 计算文件摘要...');
    const digest: Record<string, string> = {};
    for (const type of digestTypes) {
      if (['md5', 'sha1', 'sha256'].includes(type)) {
        digest[type] = await calculateDigest(fileBlob, type as any);
      }
    }
    console.log('[WPS保存] 文件摘要:', digest);

    // 第二阶段：获取上传地址
    console.log('[WPS保存] 第二阶段：获取上传地址');
    const uploadAddressParams: GetUploadAddressParams = {
      file_id: fileId,
      name: fileName,
      size: fileBlob.size,
      digest: digest,
      is_manual: isManual,
      content_type: fileBlob.type
    };

    const addressResult = await getUploadAddress(uploadAddressParams);
    console.log('[WPS保存] 上传地址:', addressResult.url);

    // 上传文件到指定地址
    console.log('[WPS保存] 上传文件...');

    let uploadResponse: Response;
    if (USE_MOCK && addressResult.url === 'mock://upload') {
      // 前端模拟 - 不实际上传，直接模拟响应
      console.log('[前端模拟] 跳过实际上传，使用模拟响应');
      uploadResponse = new Response(null, {
        status: 200,
        statusText: 'OK',
        headers: new Headers({
          'content-type': 'application/json',
          'x-mock': 'true'
        })
      });

      // 可选：将文件保存到 IndexedDB（用于更持久的存储）
      try {
        await saveFileToIndexedDB(fileId, fileBlob);
        console.log('[前端模拟] 文件已保存到 IndexedDB');
      } catch (err) {
        console.warn('[前端模拟] 保存到 IndexedDB 失败:', err);
      }
    } else {
      // 真实上传
      uploadResponse = await fetch(addressResult.url, {
        method: addressResult.method || 'PUT',
        headers: addressResult.headers || {},
        body: fileBlob
      });
    }

    console.log('[WPS保存] 上传响应状态:', uploadResponse.status);

    // 获取响应头
    const responseHeaders: Record<string, string> = {};
    uploadResponse.headers.forEach((value, key) => {
      responseHeaders[key] = value;
    });

    // 获取响应体（如果有）
    let responseBody: string | undefined;
    try {
      const bodyText = await uploadResponse.text();
      if (bodyText) {
        responseBody = btoa(bodyText); // base64 编码
      }
    } catch (err) {
      console.warn('[WPS保存] 无法读取响应体:', err);
    }

    // 第三阶段：上传完成通知
    console.log('[WPS保存] 第三阶段：上传完成通知');
    const completeParams: UploadCompleteParams = {
      file_id: fileId,
      request: uploadAddressParams,
      response: {
        status_code: uploadResponse.status,
        headers: responseHeaders,
        body: responseBody
      },
      send_back_params: addressResult.send_back_params
    };

    const fileInfo = await uploadComplete(completeParams);
    console.log('[WPS保存] 保存完成，文件信息:', fileInfo);

    return fileInfo;
  } catch (error) {
    console.error('[WPS保存] 保存失败:', error);
    throw error;
  }
};

/**
 * 前端模拟：将文件保存到 IndexedDB
 * 用于更持久的本地存储
 */
const saveFileToIndexedDB = (fileId: string, fileBlob: Blob): Promise<void> => {
  return new Promise((resolve, reject) => {
    const dbName = 'WPS_Files';
    const storeName = 'files';
    const request = indexedDB.open(dbName, 1);

    request.onerror = () => {
      reject(new Error('无法打开 IndexedDB'));
    };

    request.onsuccess = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      const transaction = db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore(storeName);

      const fileRecord = {
        id: fileId,
        blob: fileBlob,
        timestamp: Date.now()
      };

      const putRequest = store.put(fileRecord);

      putRequest.onsuccess = () => {
        resolve();
      };

      putRequest.onerror = () => {
        reject(new Error('保存文件到 IndexedDB 失败'));
      };
    };

    request.onupgradeneeded = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      if (!db.objectStoreNames.contains(storeName)) {
        db.createObjectStore(storeName, { keyPath: 'id' });
      }
    };
  });
};

/**
 * 前端模拟：从 IndexedDB 读取文件
 */
export const getFileFromIndexedDB = (fileId: string): Promise<Blob | null> => {
  return new Promise((resolve, reject) => {
    const dbName = 'WPS_Files';
    const storeName = 'files';
    const request = indexedDB.open(dbName, 1);

    request.onerror = () => {
      reject(new Error('无法打开 IndexedDB'));
    };

    request.onsuccess = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      const transaction = db.transaction([storeName], 'readonly');
      const store = transaction.objectStore(storeName);
      const getRequest = store.get(fileId);

      getRequest.onsuccess = () => {
        const result = getRequest.result;
        resolve(result ? result.blob : null);
      };

      getRequest.onerror = () => {
        reject(new Error('读取文件失败'));
      };
    };

    request.onupgradeneeded = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      if (!db.objectStoreNames.contains(storeName)) {
        db.createObjectStore(storeName, { keyPath: 'id' });
      }
    };
  });
};

/**
 * 前端模拟：清除所有保存的文件
 */
export const clearAllFiles = (): Promise<void> => {
  return new Promise((resolve, reject) => {
    // 清除 localStorage
    const keys = Object.keys(localStorage);
    keys.forEach((key) => {
      if (key.startsWith('wps_file_')) {
        localStorage.removeItem(key);
      }
    });

    // 清除 IndexedDB
    const dbName = 'WPS_Files';
    const request = indexedDB.deleteDatabase(dbName);

    request.onsuccess = () => {
      console.log('[前端模拟] 所有文件已清除');
      resolve();
    };

    request.onerror = () => {
      reject(new Error('清除 IndexedDB 失败'));
    };
  });
};

/**
 * 清空文档批注
 * @param documentId 文档ID
 */
export const cleanDocumentComments = (documentId: string | number): Promise<any> => {
  return request({
    url: `/wps/callback/v3/3rd/clean/${documentId}`,
    method: 'put'
  });
};

/**
 * 获取文档历史版本列表
 * @param ossId OSS文件ID
 */
export interface FileVersion {
  version: number;
  url: string;
  createTime: number;
  updateTime: number;
}

export const getFileVersionList = (ossId: string | number): Promise<{ data: FileVersion[] }> => {
  return request({
    url: '/wps/callback/v3/3rd/files/list',
    method: 'get',
    params: { ossId }
  });
};

/**
 * 初始化 WPS 文档
 * @param ossId OSS文件ID
 * @returns 返回当前版本号
 */
export const initWpsDocument = (ossId: string | number): Promise<{ data: number }> => {
  return request({
    url: `/wps/callback/v3/3rd/init/${ossId}`,
    method: 'post'
  });
};

/**
 * 取消 WPS 文档编辑
 * @param ossId OSS文件ID
 */
export const cancelWpsDocument = (ossId: string | number): Promise<any> => {
  return request({
    url: `/wps/callback/v3/3rd/cancel/${ossId}`,
    method: 'delete'
  });
};

/**
 * 获取最终文档信息
 * @param fileId 文件ID（格式：ossId_version）
 */
export interface FinalFileInfo {
  ossId: number;
  fileName: string;
  originalName: string;
  fileSuffix: string;
  url: string;
  ext1: string;
  createTime: string;
  createBy: number;
  createByName: string;
  service: string;
  updateTime: string;
}

export const getFinalFile = (fileId: string): Promise<{ data: FinalFileInfo }> => {
  return request({
    url: '/wps/callback/v3/3rd/getFinal',
    method: 'get',
    params: { id: fileId }
  });
};
