require 'spec_helper'

RSpec.describe Jekyll::Skyhook do
  let(:site) { create_test_site }
  let(:skyhook) { Jekyll::Skyhook.instance(site) }

  before do
    create_test_image(site, 'assets/test.jpg', 200, 200)
  end

  after do
    FileUtils.rm_rf(site.source)
    FileUtils.rm_rf(site.dest)
    FileUtils.rm_rf(site.cache_dir)
  end

  describe '#build_transform_key' do
    it 'creates key with single transformation' do
      key = skyhook.send(:build_transform_key, 'assets/test.jpg', { width: '400' })
      expect(key).to eq('assets/test.jpg#width=400')
    end

    it 'creates key with multiple transformations in sorted order' do
      key = skyhook.send(:build_transform_key, 'assets/test.jpg', { format: 'webp', width: '400' })
      expect(key).to eq('assets/test.jpg#format=webp&width=400')
    end

    it 'handles empty transformations' do
      key = skyhook.send(:build_transform_key, 'assets/test.jpg', {})
      expect(key).to eq('assets/test.jpg#')
    end
  end

  describe '#apply_transformations' do
    let(:image_path) { File.join(site.source, 'assets/test.jpg') }

    it 'applies width transformation' do
      processor = skyhook.send(:apply_transformations, image_path, { width: '100' })
      expect(processor).to be_a(ImageProcessing::Builder)
    end

    it 'applies format transformation' do
      processor = skyhook.send(:apply_transformations, image_path, { format: 'webp' })
      expect(processor).to be_a(ImageProcessing::Builder)
    end

    it 'applies multiple transformations' do
      processor = skyhook.send(:apply_transformations, image_path, { width: '100', format: 'png' })
      expect(processor).to be_a(ImageProcessing::Builder)
    end

    it 'handles empty transformations' do
      processor = skyhook.send(:apply_transformations, image_path, {})
      expect(processor).to be_a(ImageProcessing::Builder)
    end
  end

  describe '#process_image_transformation' do
    let(:image_path) { File.join(site.source, 'assets/test.jpg') }

    it 'returns nil for non-existent file' do
      result = skyhook.process_image_transformation('/nonexistent/file.jpg', { width: '100' })
      expect(result).to be_nil
    end

    it 'returns nil for empty transformations' do
      result = skyhook.process_image_transformation(image_path, {})
      expect(result).to be_nil
    end

    it 'processes width transformation' do
      result = skyhook.process_image_transformation(image_path, { width: '100' })
      expect(result).to start_with('_digested/assets/test-width100-')
      expect(result).to end_with('.jpg')
    end

    it 'processes format transformation' do
      result = skyhook.process_image_transformation(image_path, { format: 'webp' })
      expect(result).to start_with('_digested/assets/test-formatwebp-')
      expect(result).to end_with('.webp')
    end

    it 'processes multiple transformations' do
      result = skyhook.process_image_transformation(image_path, { width: '100', format: 'png' })
      expect(result).to start_with('_digested/assets/test-formatpng-width100-')
      expect(result).to end_with('.png')
    end

    it 'caches results for identical transformations' do
      transformations = { width: '100', format: 'webp' }

      result1 = skyhook.process_image_transformation(image_path, transformations)
      result2 = skyhook.process_image_transformation(image_path, transformations)

      expect(result1).to eq(result2)
    end

    it 'creates actual transformed file' do
      result = skyhook.process_image_transformation(image_path, { width: '50' })
      transformed_path = File.join(site.source, result)

      expect(File.exist?(transformed_path)).to be true

      # Verify the transformed image has correct dimensions
      transformed_image = MiniMagick::Image.open(transformed_path)
      expect(transformed_image.width).to eq(50)
    end

    it 'adds transformed file to Jekyll static files' do
      initial_count = site.static_files.size
      skyhook.process_image_transformation(image_path, { width: '100' })

      expect(site.static_files.size).to eq(initial_count + 1)
    end

    it 'updates manifest with transformation key' do
      result = skyhook.process_image_transformation(image_path, { width: '100' })
      manifest = skyhook.instance_variable_get(:@manifest)

      expect(manifest['assets/test.jpg#width=100']).to eq(result)
    end
  end

  describe '#store_version' do
    let(:original_path) { File.join(site.source, 'assets/test.jpg') }
    let(:processed_path) { create_test_image(site, 'assets/processed.png', 100, 100) }

    it 'stores processed image with correct path' do
      result = skyhook.store_version(original_path, { width: '100', format: 'png' }, processed_path)

      expect(result).to start_with('_digested/assets/test-formatpng-width100-')
      expect(result).to end_with('.png')
    end

    it 'copies processed file to digested directory' do
      result = skyhook.store_version(original_path, { width: '100' }, processed_path)
      digested_file = File.join(site.source, result)

      expect(File.exist?(digested_file)).to be true
    end

    it 'adds to manifest with transform key' do
      result = skyhook.store_version(original_path, { width: '100' }, processed_path)
      manifest = skyhook.instance_variable_get(:@manifest)

      expect(manifest['assets/test.jpg#width=100']).to eq(result)
    end

    it 'adds to Jekyll static files' do
      initial_count = site.static_files.size
      skyhook.store_version(original_path, { width: '100' }, processed_path)

      expect(site.static_files.size).to eq(initial_count + 1)
    end
  end

  describe 'manifest integration' do
    let(:image_path) { File.join(site.source, 'assets/test.jpg') }

    it 'saves and loads manifest correctly' do
      # Process a transformation
      result = skyhook.process_image_transformation(image_path, { width: '100' })
      skyhook.send(:write_manifest)

      # Create new instance to test loading
      new_skyhook = Jekyll::Skyhook.instance(site)
      manifest = new_skyhook.instance_variable_get(:@manifest)

      expect(manifest['assets/test.jpg#width=100']).to eq(result)
    end
  end

  describe 'digest generation' do
    it 'generates different digests for different transformations' do
      image_path = File.join(site.source, 'assets/test.jpg')

      result1 = skyhook.process_image_transformation(image_path, { width: '100' })
      result2 = skyhook.process_image_transformation(image_path, { width: '200' })

      # Extract digests from filenames
      digest1 = result1.match(/-([a-f0-9]{32})\./)[1]
      digest2 = result2.match(/-([a-f0-9]{32})\./)[1]

      expect(digest1).not_to eq(digest2)
    end

    it 'generates same digest for identical transformations' do
      image_path = File.join(site.source, 'assets/test.jpg')

      result1 = skyhook.process_image_transformation(image_path, { width: '100' })
      # Clear the manifest to force regeneration
      skyhook.instance_variable_get(:@manifest).clear
      result2 = skyhook.process_image_transformation(image_path, { width: '100' })

      # Extract digests from filenames
      digest1 = result1.match(/-([a-f0-9]{32})\./)[1]
      digest2 = result2.match(/-([a-f0-9]{32})\./)[1]

      expect(digest1).to eq(digest2)
    end
  end
end
