// 商店资源管理模块
// 负责获取商店中的资源列表（角色、道具、特效、Q版）

const fs = require('fs').promises;
const path = require('path');
const { readdir, stat } = require('fs').promises;
const http = require('http');

class StoreManager {
  constructor() {
    // 商店资源根目录（使用 market_data 目录）
    this.storeRoot = path.join(__dirname, '..', 'market_data');
    
    // 价格文件路径
    this.pricesFilePath = path.join(this.storeRoot, 'prices.json');
    // 分类排序文件路径
    this.categoryOrderFilePath = path.join(this.storeRoot, 'category-order.json');
    this.pricesCache = null; // 价格缓存
    this.categoriesCache = null; // 分类缓存
  }

  /**
   * 获取分类排序配置
   * @returns {Promise<Array>} 排序后的分类名称数组
   */
  async getCategoryOrder() {
    try {
      const data = await fs.readFile(this.categoryOrderFilePath, 'utf-8');
      return JSON.parse(data);
    } catch (error) {
      // 文件不存在或解析失败，返回空数组
      return [];
    }
  }

  /**
   * 保存分类排序配置
   * @param {Array} order 分类名称数组
   */
  async saveCategoryOrder(order) {
    try {
      await fs.writeFile(this.categoryOrderFilePath, JSON.stringify(order, null, 2), 'utf-8');
      this.clearCategoriesCache();
      return true;
    } catch (error) {
      console.error('[StoreManager] 保存分类排序失败:', error);
      return false;
    }
  }

  /**
   * 动态获取所有分类（读取根目录下的文件夹）
   * @returns {Promise<Array>} 分类列表，每个分类包含 name 和 dir
   */
  async getCategories() {
    try {
      if (this.categoriesCache !== null) {
        return this.categoriesCache;
      }

      const items = await readdir(this.storeRoot);
      const categories = [];

      for (const item of items) {
        const itemPath = path.join(this.storeRoot, item);
        const stats = await stat(itemPath);
        
        // 只处理文件夹，排除 prices.json 等文件和特殊目录
        if (stats.isDirectory() && item !== 'node_modules' && item !== 'temp' && !item.startsWith('.')) {
          categories.push({
            name: item, // 文件夹名称就是分类名称
            dir: item
          });
        }
      }

      // 按保存的顺序排序
      const savedOrder = await this.getCategoryOrder();
      if (savedOrder.length > 0) {
        categories.sort((a, b) => {
          const indexA = savedOrder.indexOf(a.name);
          const indexB = savedOrder.indexOf(b.name);
          // 不在排序列表中的放最后，按名称排序
          if (indexA === -1 && indexB === -1) return a.name.localeCompare(b.name);
          if (indexA === -1) return 1;
          if (indexB === -1) return -1;
          return indexA - indexB;
        });
      } else {
        // 没有保存的顺序，按名称排序
        categories.sort((a, b) => a.name.localeCompare(b.name));
      }

      this.categoriesCache = categories;
      return categories;
    } catch (error) {
      console.error('[StoreManager] 获取分类列表失败:', error);
      return [];
    }
  }

  /**
   * 清除分类缓存
   */
  clearCategoriesCache() {
    this.categoriesCache = null;
  }

  /**
   * 读取价格文件
   * @returns {Promise<Object>} 价格对象，key为资源路径，value为价格
   */
  async loadPrices() {
    try {
      if (this.pricesCache !== null) {
        return this.pricesCache;
      }
      
      const pricesData = await fs.readFile(this.pricesFilePath, 'utf-8');
      this.pricesCache = JSON.parse(pricesData);
      return this.pricesCache;
    } catch (error) {
      // 文件不存在或读取失败，返回空对象
      if (error.code === 'ENOENT') {
        this.pricesCache = {};
        return {};
      }
      console.error('[StoreManager] 读取价格文件失败:', error);
      return {};
    }
  }

  /**
   * 获取资源价格
   * @param {string} resourcePath - 资源路径
   * @returns {Promise<number>} 价格，默认为0
   */
  async getResourcePrice(resourcePath) {
    const prices = await this.loadPrices();
    return prices[resourcePath] !== undefined ? prices[resourcePath] : 0;
  }

  /**
   * 清除价格缓存（当价格更新后调用）
   */
  clearPricesCache() {
    this.pricesCache = null;
  }

  /**
   * 获取文件夹的第一帧预览图
   * @param {string} folderPath - 文件夹路径
   * @returns {Promise<{hasPreview: boolean, previewFile: string|null}>}
   */
  async getFirstFrame(folderPath) {
    const commonNames = ['01.png', '00.png', '001.png', '0001.png', '1.png', '0.png'];
    
    try {
      const items = await readdir(folderPath);
      
      // 首先检查常见的帧文件名
      for (const name of commonNames) {
        if (items.includes(name)) {
          return {
            hasPreview: true,
            previewFile: name
          };
        }
      }
      
      // 检查是否有任何PNG文件
      const pngFiles = items.filter(item => item.toLowerCase().endsWith('.png'));
      if (pngFiles.length > 0) {
        // 按文件名排序，取第一个
        pngFiles.sort();
        return {
          hasPreview: true,
          previewFile: pngFiles[0]
        };
      }
      
      return {
        hasPreview: false,
        previewFile: null
      };
    } catch (error) {
      return {
        hasPreview: false,
        previewFile: null
      };
    }
  }

  /**
   * 获取指定分类的资源列表
   * @param {string} categoryDir - 分类文件夹名称（直接使用文件夹名称）
   * @returns {Promise<Array>} 资源列表
   */
  async getResourcesByCategory(categoryDir) {
    if (!categoryDir) {
      return [];
    }

    const categoryPath = path.join(this.storeRoot, categoryDir);
    
    try {
      // 检查目录是否存在
      await fs.access(categoryPath);
      
      const items = await readdir(categoryPath);
      const resources = [];

      for (const item of items) {
        const itemPath = path.join(categoryPath, item);
        const stats = await stat(itemPath);
        
        // 只处理文件夹
        if (stats.isDirectory()) {
          // 获取第一帧预览图
          const previewInfo = await this.getFirstFrame(itemPath);
          
          // 获取文件夹中的PNG文件数量
          const files = await readdir(itemPath);
          const pngCount = files.filter(f => f.toLowerCase().endsWith('.png')).length;
          
          const resourcePath = `${categoryDir}/${item}`;
          
          // 获取资源价格
          const price = await this.getResourcePrice(resourcePath);
          
          const resource = {
            name: item,
            category: categoryDir, // 分类名称就是文件夹名称
            categoryDir: categoryDir,
            previewUrl: previewInfo.hasPreview 
              ? `/api/store/preview?category=${encodeURIComponent(categoryDir)}&folder=${encodeURIComponent(item)}&file=${encodeURIComponent(previewInfo.previewFile)}`
              : null,
            frameCount: pngCount,
            path: resourcePath,
            points: price // 添加价格信息
          };
          
          resources.push(resource);
        }
      }
      
      // 按名称排序
      resources.sort((a, b) => a.name.localeCompare(b.name));
      
      return resources;
    } catch (error) {
      console.error(`[StoreManager] 获取分类资源失败: ${categoryDir}`, error);
      return [];
    }
  }

  /**
   * 获取所有资源（可选的分类筛选）
   * @param {string|null} category - 分类名称，null 表示所有分类
   * @param {string|null} searchQuery - 搜索关键词
   * @returns {Promise<Array>} 资源列表
   */
  async getAllResources(category = null, searchQuery = null) {
    let allResources = [];
    
    if (category) {
      // 只获取指定分类
      allResources = await this.getResourcesByCategory(category);
    } else {
      // 获取所有分类
      const categories = await this.getCategories();
      for (const cat of categories) {
        const resources = await this.getResourcesByCategory(cat.dir);
        allResources = allResources.concat(resources);
      }
    }
    
    // 搜索筛选
    if (searchQuery && searchQuery.trim()) {
      const query = searchQuery.trim().toLowerCase();
      allResources = allResources.filter(resource => 
        resource.name.toLowerCase().includes(query)
      );
    }
    
    return allResources;
  }

  /**
   * 处理获取分类列表的 API 请求
   * @param {http.IncomingMessage} req - HTTP 请求对象
   * @param {http.ServerResponse} res - HTTP 响应对象
   */
  async handleGetCategories(req, res) {
    try {
      const categories = await this.getCategories();
      
      res.writeHead(200, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      });
      res.end(JSON.stringify({
        success: true,
        categories: categories,
        count: categories.length
      }));
    } catch (error) {
      console.error('[StoreManager] 获取分类列表失败:', error);
      res.writeHead(500, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      });
      res.end(JSON.stringify({
        success: false,
        error: error.message
      }));
    }
  }

  /**
   * 处理获取资源列表的 API 请求
   * @param {http.IncomingMessage} req - HTTP 请求对象
   * @param {http.ServerResponse} res - HTTP 响应对象
   */
  async handleGetResources(req, res) {
    const parsedUrl = require('url').parse(req.url, true);
    const { category, search } = parsedUrl.query;
    
    try {
      const resources = await this.getAllResources(category || null, search || null);
      
      res.writeHead(200, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      });
      res.end(JSON.stringify({
        success: true,
        resources: resources,
        count: resources.length
      }));
    } catch (error) {
      console.error('[StoreManager] 获取资源列表失败:', error);
      res.writeHead(500, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      });
      res.end(JSON.stringify({
        success: false,
        error: error.message
      }));
    }
  }

  /**
   * 处理预览图请求
   * @param {http.IncomingMessage} req - HTTP 请求对象
   * @param {http.ServerResponse} res - HTTP 响应对象
   */
  async handlePreview(req, res) {
    const parsedUrl = require('url').parse(req.url, true);
    const { category, folder, file } = parsedUrl.query;
    
    if (!category || !folder || !file) {
      res.writeHead(400, { 'Content-Type': 'text/plain' });
      res.end('Missing parameters');
      return;
    }
    
    try {
      const filePath = path.join(this.storeRoot, category, folder, file);
      
      // 安全检查：确保文件在商店目录内
      const normalizedPath = path.normalize(filePath);
      const normalizedRoot = path.normalize(this.storeRoot);
      if (!normalizedPath.startsWith(normalizedRoot)) {
        res.writeHead(403, { 'Content-Type': 'text/plain' });
        res.end('Access denied');
        return;
      }
      
      // 检查文件是否存在
      await fs.access(filePath);
      
      // 读取文件并返回
      const fileData = await fs.readFile(filePath);
      
      res.writeHead(200, {
        'Content-Type': 'image/png',
        'Access-Control-Allow-Origin': '*',
        'Cache-Control': 'public, max-age=3600'
      });
      res.end(fileData);
    } catch (error) {
      console.error('[StoreManager] 获取预览图失败:', error);
      res.writeHead(404, { 'Content-Type': 'text/plain' });
      res.end('File not found');
    }
  }

  /**
   * 处理获取帧列表的 API 请求（用于播放动画）
   * @param {http.IncomingMessage} req - HTTP 请求对象
   * @param {http.ServerResponse} res - HTTP 响应对象
   */
  async handleGetFrames(req, res) {
    const parsedUrl = require('url').parse(req.url, true);
    const { category, folder } = parsedUrl.query;
    
    if (!category || !folder) {
      res.writeHead(400, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      });
      res.end(JSON.stringify({
        success: false,
        error: 'Missing parameters'
      }));
      return;
    }
    
    try {
      const folderPath = path.join(this.storeRoot, category, folder);
      
      // 安全检查
      const normalizedPath = path.normalize(folderPath);
      const normalizedRoot = path.normalize(this.storeRoot);
      if (!normalizedPath.startsWith(normalizedRoot)) {
        res.writeHead(403, {
          'Content-Type': 'application/json',
          'Access-Control-Allow-Origin': '*'
        });
        res.end(JSON.stringify({
          success: false,
          error: 'Access denied'
        }));
        return;
      }
      
      const files = await readdir(folderPath);
      
      // 过滤PNG文件并按数字排序
      const pngFiles = files
        .filter(file => file.toLowerCase().endsWith('.png'))
        .map(file => {
          let frameNum = null;
          // 先尝试匹配纯数字格式：00.png, 01.png
          let match = /^(\d+)\.png$/i.exec(file);
          if (match) {
            frameNum = parseInt(match[1], 10);
          } else {
            // 再尝试匹配文件名末尾的数字格式
            match = /(\d+)\.png$/i.exec(file);
            if (match) {
              frameNum = parseInt(match[1], 10);
            }
          }
          
          if (frameNum !== null) {
            return {
              frameNum: frameNum,
              fileName: file,
              url: `/api/store/frame?category=${encodeURIComponent(category)}&folder=${encodeURIComponent(folder)}&file=${encodeURIComponent(file)}`
            };
          }
          return null;
        })
        .filter(item => item !== null)
        .sort((a, b) => a.frameNum - b.frameNum);
      
      res.writeHead(200, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      });
      res.end(JSON.stringify({
        success: true,
        frames: pngFiles.map(item => item.frameNum),
        fileNames: pngFiles.map(item => item.fileName),
        frameUrls: pngFiles.map(item => item.url),
        maxFrame: pngFiles.length > 0 ? Math.max(...pngFiles.map(item => item.frameNum)) : 0
      }));
    } catch (error) {
      console.error('[StoreManager] 获取帧列表失败:', error);
      res.writeHead(500, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
      });
      res.end(JSON.stringify({
        success: false,
        error: error.message
      }));
    }
  }

  /**
   * 处理帧图片请求
   * @param {http.IncomingMessage} req - HTTP 请求对象
   * @param {http.ServerResponse} res - HTTP 响应对象
   */
  async handleGetFrame(req, res) {
    const parsedUrl = require('url').parse(req.url, true);
    const { category, folder, file } = parsedUrl.query;
    
    if (!category || !folder || !file) {
      res.writeHead(400, { 'Content-Type': 'text/plain' });
      res.end('Missing parameters');
      return;
    }
    
    try {
      const filePath = path.join(this.storeRoot, category, folder, file);
      
      // 安全检查
      const normalizedPath = path.normalize(filePath);
      const normalizedRoot = path.normalize(this.storeRoot);
      if (!normalizedPath.startsWith(normalizedRoot)) {
        res.writeHead(403, { 'Content-Type': 'text/plain' });
        res.end('Access denied');
        return;
      }
      
      await fs.access(filePath);
      const fileData = await fs.readFile(filePath);
      
      res.writeHead(200, {
        'Content-Type': 'image/png',
        'Access-Control-Allow-Origin': '*',
        'Cache-Control': 'public, max-age=3600'
      });
      res.end(fileData);
    } catch (error) {
      console.error('[StoreManager] 获取帧图片失败:', error);
      res.writeHead(404, { 'Content-Type': 'text/plain' });
      res.end('File not found');
    }
  }
}

module.exports = StoreManager;

