import { cloneDeep } from 'lodash';

import { musicDB } from '@/hooks/MusicHook';
import { SongSourceConfigManager } from '@/services/SongSourceConfigManager';
import { useSettingsStore } from '@/store';
import type { SongResult } from '@/types/music';
import { isElectron } from '@/utils';
import requestMusic from '@/utils/request_music';

import type { ParsedMusicResult } from './gdmusic';
import { parseFromGDMusic } from './gdmusic';
import { LxMusicStrategy } from './lxMusicStrategy';
import { parseFromCustomApi } from './parseFromCustomApi';

const { saveData, getData, deleteData } = musicDB;

/**
 * 音乐解析结果接口
 */
export interface MusicParseResult {
  data: {
    code: number;
    message: string;
    data?: {
      url: string;
      [key: string]: any;
    };
  };
}

/**
 * 缓存配置
 */
const CACHE_CONFIG = {
  // 音乐URL缓存时间：30分钟
  MUSIC_URL_CACHE_TIME: 30 * 60 * 1000,
  // 失败缓存时间：1分钟（减少到 1 分钟以便更快恢复）
  FAILED_CACHE_TIME: 1 * 60 * 1000,
  // 重试配置
  MAX_RETRY_COUNT: 2,
  RETRY_DELAY: 1000
};

/**
 * 内存失败缓存（替代 IndexedDB，更轻量且应用重启后自动失效）
 */
const failedCacheMap = new Map<string, number>();

/**
 * 缓存管理器
 */
export class CacheManager {
  /**
   * 获取缓存的音乐URL
   */
  static async getCachedMusicUrl(
    id: number,
    musicSources?: string[]
  ): Promise<MusicParseResult | null> {
    try {
      const cached = await getData('music_url_cache', id);
      if (
        cached?.createTime &&
        Date.now() - cached.createTime < CACHE_CONFIG.MUSIC_URL_CACHE_TIME
      ) {
        // 检查缓存的音源配置是否与当前配置一致
        const cachedSources = cached.musicSources || [];
        const currentSources = musicSources || [];

        // 如果音源配置不一致，清除缓存
        if (JSON.stringify(cachedSources.sort()) !== JSON.stringify(currentSources.sort())) {
          console.log(`音源配置已变更，清除歌曲 ${id} 的缓存`);
          await deleteData('music_url_cache', id);
          return null;
        }

        console.log(`使用缓存的音乐URL: ${id}`);
        return cached.data;
      }
      // 清理过期缓存
      if (cached) {
        await deleteData('music_url_cache', id);
      }
    } catch (error) {
      console.warn('获取缓存失败:', error);
    }
    return null;
  }

  /**
   * 缓存音乐URL
   */
  static async setCachedMusicUrl(
    id: number,
    result: MusicParseResult,
    musicSources?: string[]
  ): Promise<void> {
    try {
      // 深度克隆数据，确保可以被 IndexedDB 存储
      await saveData('music_url_cache', {
        id,
        data: cloneDeep(result),
        musicSources: cloneDeep(musicSources || []),
        createTime: Date.now()
      });
      console.log(`缓存音乐URL成功: ${id}`);
    } catch (error) {
      console.error('缓存音乐URL失败:', error);
    }
  }

  /**
   * 检查是否在失败缓存期内（使用内存缓存）
   */
  static isInFailedCache(id: number, strategyName: string): boolean {
    const cacheKey = `${id}_${strategyName}`;
    const cachedTime = failedCacheMap.get(cacheKey);
    if (cachedTime && Date.now() - cachedTime < CACHE_CONFIG.FAILED_CACHE_TIME) {
      console.log(`策略 ${strategyName} 在失败缓存期内，跳过`);
      return true;
    }
    // 清理过期缓存
    if (cachedTime) {
      failedCacheMap.delete(cacheKey);
    }
    return false;
  }

  /**
   * 添加失败缓存（使用内存缓存）
   */
  static addFailedCache(id: number, strategyName: string): void {
    const cacheKey = `${id}_${strategyName}`;
    failedCacheMap.set(cacheKey, Date.now());
    console.log(
      `添加失败缓存成功: ${strategyName} (缓存时间: ${CACHE_CONFIG.FAILED_CACHE_TIME / 1000}秒)`
    );
  }

  /**
   * 清除指定歌曲的失败缓存
   */
  static clearFailedCache(id: number): void {
    const keysToDelete: string[] = [];
    failedCacheMap.forEach((_, key) => {
      if (key.startsWith(`${id}_`)) {
        keysToDelete.push(key);
      }
    });
    keysToDelete.forEach((key) => failedCacheMap.delete(key));
    if (keysToDelete.length > 0) {
      console.log(`清除歌曲 ${id} 的失败缓存: ${keysToDelete.length} 项`);
    }
  }

  /**
   * 清除指定歌曲的所有缓存
   */
  static async clearMusicCache(id: number): Promise<void> {
    try {
      // 清除URL缓存
      await deleteData('music_url_cache', id);
      console.log(`清除歌曲 ${id} 的URL缓存`);

      // 清除失败缓存 - 需要遍历所有策略
      const strategies = ['custom', 'gdmusic', 'unblockMusic'];
      for (const strategy of strategies) {
        const cacheKey = `${id}_${strategy}`;
        try {
          await deleteData('music_failed_cache', cacheKey);
        } catch {
          // 忽略删除不存在缓存的错误
        }
      }
      console.log(`清除歌曲 ${id} 的失败缓存`);
    } catch (error) {
      console.error('清除缓存失败:', error);
    }
  }
}

/**
 * 重试工具
 */
class RetryHelper {
  /**
   * 带重试的异步执行
   */
  static async withRetry<T>(
    fn: () => Promise<T>,
    maxRetries = CACHE_CONFIG.MAX_RETRY_COUNT,
    delay = CACHE_CONFIG.RETRY_DELAY
  ): Promise<T> {
    let lastError: Error;

    for (let i = 0; i <= maxRetries; i++) {
      try {
        return await fn();
      } catch (error) {
        lastError = error as Error;
        if (i < maxRetries) {
          console.log(`重试第 ${i + 1} 次，延迟 ${delay}ms`);
          await new Promise((resolve) => setTimeout(resolve, delay));
          delay *= 2; // 指数退避
        }
      }
    }

    throw lastError!;
  }
}

/**
 * 从GD音乐台获取音频URL
 * @param id 歌曲ID
 * @param data 歌曲数据
 * @returns 解析结果，失败时返回null
 */
const getGDMusicAudio = async (id: number, data: SongResult): Promise<ParsedMusicResult | null> => {
  try {
    const gdResult = await parseFromGDMusic(id, data, '999');
    if (gdResult) {
      return gdResult;
    }
  } catch (error) {
    console.error('GD音乐台解析失败:', error);
  }
  return null;
};

/**
 * 使用unblockMusic解析音频URL
 * @param id 歌曲ID
 * @param data 歌曲数据
 * @param sources 音源列表
 * @returns 解析结果
 */
const getUnblockMusicAudio = (id: number, data: SongResult, sources: any[]) => {
  const filteredSources = sources.filter((source) => source !== 'gdmusic');
  console.log(`使用unblockMusic解析，音源:`, filteredSources);
  return window.api.unblockMusic(id, cloneDeep(data), cloneDeep(filteredSources));
};

/**
 * 统一的解析结果适配器
 */
const adaptParseResult = (result: any): MusicParseResult | null => {
  if (!result) return null;

  // 如果已经是标准格式
  if (result.data?.code !== undefined && result.data?.message !== undefined) {
    return result;
  }

  // 适配GD音乐台的返回格式
  if (result.data?.data?.url) {
    return {
      data: {
        code: 200,
        message: 'success',
        data: {
          url: result.data.data.url,
          ...result.data.data
        }
      }
    };
  }

  // 适配其他格式
  if (result.url) {
    return {
      data: {
        code: 200,
        message: 'success',
        data: {
          url: result.url,
          ...result
        }
      }
    };
  }

  return null;
};

/**
 * 音源解析策略接口
 */
interface MusicSourceStrategy {
  name: string;
  priority: number;
  canHandle: (sources: string[], settingsStore?: any) => boolean;
  parse: (
    id: number,
    data: SongResult,
    quality?: string,
    sources?: string[]
  ) => Promise<MusicParseResult | null>;
}

/**
 * 自定义API解析策略
 */
class CustomApiStrategy implements MusicSourceStrategy {
  name = 'custom';
  priority = 1;

  canHandle(sources: string[], settingsStore?: any): boolean {
    return sources.includes('custom') && Boolean(settingsStore?.setData?.customApiPlugin);
  }

  async parse(id: number, data: SongResult, quality = 'higher'): Promise<MusicParseResult | null> {
    // 检查失败缓存
    if (CacheManager.isInFailedCache(id, this.name)) {
      return null;
    }

    try {
      console.log('尝试使用自定义API解析...');
      const result = await RetryHelper.withRetry(async () => {
        return await parseFromCustomApi(id, data, quality);
      });

      const adaptedResult = adaptParseResult(result);
      if (adaptedResult?.data?.data?.url) {
        console.log('自定义API解析成功');
        return adaptedResult;
      }

      // 解析失败，添加失败缓存
      CacheManager.addFailedCache(id, this.name);
      return null;
    } catch (error) {
      console.error('自定义API解析失败:', error);
      CacheManager.addFailedCache(id, this.name);
      return null;
    }
  }
}

/**
 * GD音乐台解析策略
 */
class GDMusicStrategy implements MusicSourceStrategy {
  name = 'gdmusic';
  priority = 3;

  canHandle(sources: string[]): boolean {
    return sources.includes('gdmusic');
  }

  async parse(id: number, data: SongResult): Promise<MusicParseResult | null> {
    // 检查失败缓存
    if (CacheManager.isInFailedCache(id, this.name)) {
      return null;
    }

    try {
      console.log('尝试使用GD音乐台解析...');
      const result = await RetryHelper.withRetry(async () => {
        return await getGDMusicAudio(id, data);
      });

      const adaptedResult = adaptParseResult(result);
      if (adaptedResult?.data?.data?.url) {
        console.log('GD音乐台解析成功');
        return adaptedResult;
      }

      // 解析失败，添加失败缓存
      CacheManager.addFailedCache(id, this.name);
      return null;
    } catch (error) {
      console.error('GD音乐台解析失败:', error);
      CacheManager.addFailedCache(id, this.name);
      return null;
    }
  }
}

/**
 * UnblockMusic解析策略
 */
class UnblockMusicStrategy implements MusicSourceStrategy {
  name = 'unblockMusic';
  priority = 4;

  canHandle(sources: string[]): boolean {
    const unblockSources = sources.filter((source) => !['custom', 'gdmusic'].includes(source));
    return unblockSources.length > 0;
  }

  async parse(
    id: number,
    data: SongResult,
    _quality?: string,
    sources?: string[]
  ): Promise<MusicParseResult | null> {
    // 检查失败缓存
    if (CacheManager.isInFailedCache(id, this.name)) {
      return null;
    }

    try {
      const unblockSources = (sources || []).filter(
        (source) => !['custom', 'gdmusic'].includes(source)
      );
      console.log('尝试使用UnblockMusic解析:', unblockSources);

      const result = await RetryHelper.withRetry(async () => {
        return await getUnblockMusicAudio(id, data, unblockSources);
      });

      const adaptedResult = adaptParseResult(result);
      if (adaptedResult?.data?.data?.url) {
        console.log('UnblockMusic解析成功');
        return adaptedResult;
      }

      // 解析失败，添加失败缓存
      CacheManager.addFailedCache(id, this.name);
      return null;
    } catch (error) {
      console.error('UnblockMusic解析失败:', error);
      CacheManager.addFailedCache(id, this.name);
      return null;
    }
  }
}

/**
 * 音源策略工厂
 */
class MusicSourceStrategyFactory {
  private static strategies: MusicSourceStrategy[] = [
    new LxMusicStrategy(),
    new CustomApiStrategy(),
    new GDMusicStrategy(),
    new UnblockMusicStrategy()
  ];

  /**
   * 获取可用的解析策略
   * @param sources 音源列表
   * @param settingsStore 设置存储
   * @returns 排序后的可用策略列表
   */
  static getAvailableStrategies(sources: string[], settingsStore?: any): MusicSourceStrategy[] {
    return this.strategies
      .filter((strategy) => strategy.canHandle(sources, settingsStore))
      .sort((a, b) => a.priority - b.priority);
  }
}

/**
 * 获取音源配置
 * @param id 歌曲ID
 * @param settingsStore 设置存储
 * @returns 音源列表和音质设置
 */
const getMusicConfig = (id: number, settingsStore?: any) => {
  let musicSources: string[] = [];
  let quality = 'higher';

  try {
    // 尝试获取歌曲自定义音源（使用 SongSourceConfigManager）
    const songConfig = SongSourceConfigManager.getConfig(id);
    if (songConfig && songConfig.sources.length > 0) {
      musicSources = songConfig.sources;
      console.log(`使用歌曲 ${id} 自定义音源:`, musicSources);
    }

    // 如果没有自定义音源，使用全局设置
    if (musicSources.length === 0) {
      musicSources = settingsStore?.setData?.enabledMusicSources || [];
      console.log('使用全局音源设置:', musicSources);
    }

    quality = settingsStore?.setData?.musicQuality || 'higher';
  } catch (error) {
    console.error('读取音源配置失败，使用默认配置:', error);
    musicSources = [];
    quality = 'higher';
  }

  return { musicSources, quality };
};

/**
 * 音乐解析器主类
 */
export class MusicParser {
  /**
   * 解析音乐URL
   * @param id 歌曲ID
   * @param data 歌曲数据
   * @returns 解析结果
   */
  static async parseMusic(id: number, data: SongResult): Promise<MusicParseResult> {
    const startTime = performance.now();

    try {
      // 非Electron环境直接使用API请求
      if (!isElectron) {
        console.log('非Electron环境，使用API请求');
        return await requestMusic.get<any>('/music', { params: { id } });
      }

      // 获取设置存储
      let settingsStore: any;
      try {
        settingsStore = useSettingsStore();
      } catch (error) {
        console.error('无法获取设置存储，使用后备方案:', error);
        return await requestMusic.get<any>('/music', { params: { id } });
      }

      // 获取音源配置
      const { musicSources, quality } = getMusicConfig(id, settingsStore);

      // 检查缓存（传入音源配置用于验证缓存有效性）
      console.log(`检查歌曲 ${id} 的缓存...`);
      const cachedResult = await CacheManager.getCachedMusicUrl(id, musicSources);
      if (cachedResult) {
        const endTime = performance.now();
        console.log(`✅ 命中缓存，歌曲 ${id}，耗时: ${(endTime - startTime).toFixed(2)}ms`);
        return cachedResult;
      }
      console.log(`❌ 未命中缓存，歌曲 ${id}，开始解析...`);

      // 检查音乐解析功能是否启用
      if (!settingsStore?.setData?.enableMusicUnblock) {
        console.log('音乐解析功能已禁用');
        return {
          data: {
            code: 404,
            message: '音乐解析功能已禁用',
            data: undefined
          }
        };
      }

      if (musicSources.length === 0) {
        console.warn('没有配置可用的音源，使用后备方案');
        return await requestMusic.get<any>('/music', { params: { id } });
      }

      // 获取可用的解析策略
      const availableStrategies = MusicSourceStrategyFactory.getAvailableStrategies(
        musicSources,
        settingsStore
      );

      if (availableStrategies.length === 0) {
        console.warn('没有可用的解析策略，使用后备方案');
        return await requestMusic.get<any>('/music', { params: { id } });
      }

      console.log(
        `开始解析歌曲 ${id}，可用策略:`,
        availableStrategies.map((s) => s.name)
      );

      // 按优先级依次尝试解析策略
      for (const strategy of availableStrategies) {
        try {
          const result = await strategy.parse(id, data, quality, musicSources);
          if (result?.data?.data?.url) {
            const endTime = performance.now();
            console.log(
              `解析成功，使用策略: ${strategy.name}，耗时: ${(endTime - startTime).toFixed(2)}ms`
            );

            // 缓存成功结果（包含音源配置）
            await CacheManager.setCachedMusicUrl(id, result, musicSources);

            return result;
          }
          console.log(`策略 ${strategy.name} 解析失败，继续尝试下一个策略`);
        } catch (error) {
          console.error(`策略 ${strategy.name} 解析异常:`, error);
          // 继续尝试下一个策略
        }
      }

      console.warn('所有解析策略都失败了，使用后备方案');
    } catch (error) {
      console.error('MusicParser.parseMusic 执行异常，使用后备方案:', error);
    }

    // 后备方案：使用API请求
    try {
      console.log('使用后备方案：API请求');
      const result = await requestMusic.get<any>('/music', { params: { id } });

      // 如果后备方案成功，也进行缓存
      if (result?.data?.data?.url) {
        console.log('后备方案成功，缓存结果');
        await CacheManager.setCachedMusicUrl(id, result, []);
      }

      return result;
    } catch (apiError) {
      console.error('API请求也失败了:', apiError);
      const endTime = performance.now();
      console.log(`总耗时: ${(endTime - startTime).toFixed(2)}ms`);
      return {
        data: {
          code: 500,
          message: '所有解析方式都失败了',
          data: undefined
        }
      };
    }
  }
}
