# frozen_string_literal: true

require 'spec_helper'
require 'tmpdir'
require 'fileutils'
require 'zip'

RSpec.describe 'UpgradePackageCreator' do
  # 提取核心方法进行测试
  def build_manifest(files)
    {
      version: '1.0',
      created_at: Time.now.iso8601,
      files: files.map do |f|
        {
          source: f['source'],
          target: f['target'],
          description: f['description'] || ''
        }
      end
    }
  end

  def add_files_to_zip(zipfile, base_dir, relative_path)
    full_path = File.join(base_dir, relative_path)

    if File.directory?(full_path)
      unless relative_path.empty?
        # 添加目录条目（使用 add_stored 添加一个目录条目）
        zipfile.add(relative_path, full_path)
      end
      Dir.entries(full_path).reject { |e| e.start_with?('.') }.each do |entry|
        new_path = relative_path.empty? ? entry : "#{relative_path}/#{entry}"
        add_files_to_zip(zipfile, base_dir, new_path)
      end
    else
      zipfile.add(relative_path, full_path)
    end
  end

  let(:temp_dir) { Dir.mktmpdir }
  let(:output_dir) { Dir.mktmpdir }

  after do
    FileUtils.rm_rf(temp_dir) if temp_dir
    FileUtils.rm_rf(output_dir) if output_dir
  end

  describe '#build_manifest' do
    it '生成正确格式的manifest' do
      files = [
        { 'source' => 'test.txt', 'target' => '/tmp/test.txt', 'description' => '测试文件' }
      ]
      manifest = build_manifest(files)

      expect(manifest[:version]).to eq('1.0')
      expect(manifest[:files].size).to eq(1)
      expect(manifest[:files][0][:source]).to eq('test.txt')
      expect(manifest[:files][0][:target]).to eq('/tmp/test.txt')
    end

    it '处理空描述' do
      files = [
        { 'source' => 'test.txt', 'target' => '/tmp/test.txt' }
      ]
      manifest = build_manifest(files)

      expect(manifest[:files][0][:description]).to eq('')
    end
  end

  describe '#add_files_to_zip' do
    it '添加文件到ZIP' do
      # 创建测试文件
      test_file = File.join(temp_dir, 'test.txt')
      File.write(test_file, 'hello world')

      zip_path = File.join(output_dir, 'test.zip')
      Zip::File.open(zip_path, Zip::File::CREATE) do |zipfile|
        add_files_to_zip(zipfile, temp_dir, 'test.txt')
      end

      # 验证ZIP内容
      Zip::File.open(zip_path) do |zipfile|
        names = zipfile.entries.map(&:name)
        expect(names).to include('test.txt')
        content = zipfile.read('test.txt')
        expect(content).to eq('hello world')
      end
    end

    it '添加目录及内容到ZIP' do
      # 创建测试目录和文件
      test_subdir = File.join(temp_dir, 'subdir')
      FileUtils.mkdir_p(test_subdir)
      File.write(File.join(test_subdir, 'file1.txt'), 'content 1')
      File.write(File.join(test_subdir, 'file2.txt'), 'content 2')

      zip_path = File.join(output_dir, 'test.zip')
      Zip::File.open(zip_path, Zip::File::CREATE) do |zipfile|
        add_files_to_zip(zipfile, temp_dir, 'subdir')
      end

      # 验证ZIP内容
      Zip::File.open(zip_path) do |zipfile|
        names = zipfile.entries.map(&:name).sort
        expect(names).to include('subdir/')
        expect(names).to include('subdir/file1.txt')
        expect(names).to include('subdir/file2.txt')
      end
    end

    it '处理多层嵌套目录' do
      # 创建嵌套目录结构
      nested_dir = File.join(temp_dir, 'level1', 'level2')
      FileUtils.mkdir_p(nested_dir)
      File.write(File.join(nested_dir, 'deep.txt'), 'deep content')

      zip_path = File.join(output_dir, 'test.zip')
      Zip::File.open(zip_path, Zip::File::CREATE) do |zipfile|
        add_files_to_zip(zipfile, temp_dir, 'level1')
      end

      # 验证ZIP内容
      Zip::File.open(zip_path) do |zipfile|
        names = zipfile.entries.map(&:name).sort
        expect(names).to include('level1/')
        expect(names).to include('level1/level2/')
        expect(names).to include('level1/level2/deep.txt')
      end
    end
  end

  describe '端到端测试' do
    it '完整创建升级包流程' do
      # 准备测试文件
      test_dir = File.join(temp_dir, 'test_dir')
      FileUtils.mkdir_p(test_dir)
      File.write(File.join(test_dir, 'file1.txt'), 'file 1 content')
      File.write(File.join(test_dir, 'file2.txt'), 'file 2 content')

      single_file = File.join(temp_dir, 'standalone.txt')
      File.write(single_file, 'standalone content')

      # 创建ZIP包
      package_dir = File.join(output_dir, 'package')
      FileUtils.mkdir_p(package_dir)
      zip_path = File.join(package_dir, 'upgrade.zip')

      files = [
        { 'source_path' => test_dir, 'source' => 'test_dir', 'target' => '/tmp/upgrade/test_dir', 'description' => '测试目录' },
        { 'source_path' => single_file, 'source' => 'standalone.txt', 'target' => '/tmp/upgrade/standalone.txt', 'description' => '独立文件' }
      ]

      Zip::File.open(zip_path, Zip::File::CREATE) do |zipfile|
        files.each do |f|
          add_files_to_zip(zipfile, temp_dir, f['source'])
        end
      end

      # 验证ZIP包含所有文件
      Zip::File.open(zip_path) do |zipfile|
        names = zipfile.entries.map(&:name).sort
        expect(names).to include('test_dir/')
        expect(names).to include('test_dir/file1.txt')
        expect(names).to include('test_dir/file2.txt')
        expect(names).to include('standalone.txt')
      end

      # 验证manifest（模拟）
      manifest = build_manifest(files)
      expect(manifest[:files].size).to eq(2)
      expect(manifest[:files][0][:source]).to eq('test_dir')
      expect(manifest[:files][0][:target]).to eq('/tmp/upgrade/test_dir')
    end
  end
end
