require 'spec_helper'

RSpec.describe 'Mixed Assets Integration' do
  let(:site) { create_test_site }
  let(:context) { create_liquid_context(site) }
  let(:skyhook) { Jekyll::Skyhook.instance(site) }

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

  describe 'complete asset processing workflow' do
    before do
      # Create a realistic asset structure
      create_test_image(site, 'assets/images/hero.jpg', 1200, 800)
      create_test_image(site, 'assets/images/logo.png', 200, 100)
      create_test_image(site, 'assets/images/icons/close.svg', 24, 24)
      create_test_image(site, 'assets/fonts/icons.woff', 50, 50)

      # CSS with multiple asset references
      css_content = <<~CSS
        /* Main styles */
        body {
          font-family: 'Arial', sans-serif;
          margin: 0;
          padding: 0;
        }

        .header {
          background: url('../images/hero.jpg') center/cover;
          height: 400px;
          position: relative;
        }

        .logo {
          background-image: url('../images/logo.png');
          width: 200px;
          height: 100px;
          background-size: contain;
        }

        .close-btn {
          background: url('../images/icons/close.svg') center/contain;
          width: 24px;
          height: 24px;
        }

        @font-face {
          font-family: 'Icons';
          src: url('../fonts/icons.woff') format('woff');
        }
      CSS
      create_test_css(site, 'assets/css/main.css', css_content)

      # JavaScript file
      js_content = <<~JS
        // Main application script
        const App = {
          init() {
            console.log('App initialized');
            this.bindEvents();
          },

          bindEvents() {
            document.addEventListener('DOMContentLoaded', () => {
              const closeBtn = document.querySelector('.close-btn');
              if (closeBtn) {
                closeBtn.addEventListener('click', this.handleClose);
              }
            });
          },

          handleClose(event) {
            event.preventDefault();
            console.log('Close button clicked');
          }
        };

        App.init();
      JS
      create_test_js(site, 'assets/js/app.js', js_content)

      # Process all assets
      skyhook.process_assets
    end

    it 'processes all asset types correctly' do
      # Verify manifest contains all assets
      manifest_path = File.join(site.cache_dir, 'skyhook', 'assets-manifest.json')
      manifest = JSON.parse(File.read(manifest_path))

      expect(manifest.keys).to include('assets/images/hero.jpg')
      expect(manifest.keys).to include('assets/images/logo.png')
      expect(manifest.keys).to include('assets/images/icons/close.svg')
      expect(manifest.keys).to include('assets/fonts/icons.woff')
      expect(manifest.keys).to include('assets/css/main.css')
      expect(manifest.keys).to include('assets/js/app.js')
    end

    it 'rewrites CSS URLs to point to digested assets' do
      # Get processed CSS
      tag = create_tag(Jekyll::Tags::AssetTag, 'assets/css/main.css')
      digested_css_path = tag.render(context)
      full_css_path = File.join(site.source, digested_css_path[1..-1])

      processed_css = File.read(full_css_path)

      # All URLs should be rewritten to digested paths
      expect(processed_css).to include('url(/_digested/assets/images/hero-')
      expect(processed_css).to include('url(/_digested/assets/images/logo-')
      expect(processed_css).to include('url(/_digested/assets/images/icons/close-')
      expect(processed_css).to include('url(/_digested/assets/fonts/icons-')

      # Original URLs should be gone
      expect(processed_css).not_to include("url('../images/hero.jpg')")
      expect(processed_css).not_to include("url('../images/logo.png')")
      expect(processed_css).not_to include("url('../images/icons/close.svg')")
      expect(processed_css).not_to include("url('../fonts/icons.woff')")
    end

    it 'preserves JavaScript content without modification' do
      tag = create_tag(Jekyll::Tags::AssetTag, 'assets/js/app.js')
      digested_js_path = tag.render(context)
      full_js_path = File.join(site.source, digested_js_path[1..-1])

      processed_js = File.read(full_js_path)
      original_js_path = File.join(site.source, 'assets/js/app.js')
      original_js = File.read(original_js_path)

      # JavaScript should be unchanged (just copied with digest)
      expect(processed_js).to eq(original_js)
    end

    it 'generates unique digests for each asset' do
      # Get all asset paths using tags
      css_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/css/main.css')
      js_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/js/app.js')
      hero_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/images/hero.jpg')
      logo_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/images/logo.png')

      css_path = css_tag.render(context)
      js_path = js_tag.render(context)
      hero_path = hero_tag.render(context)
      logo_path = logo_tag.render(context)

      # Extract digests
      css_digest = css_path.match(/-([a-f0-9]{32})\./)[1]
      js_digest = js_path.match(/-([a-f0-9]{32})\./)[1]
      hero_digest = hero_path.match(/-([a-f0-9]{32})\./)[1]
      logo_digest = logo_path.match(/-([a-f0-9]{32})\./)[1]

      # All digests should be unique
      digests = [css_digest, js_digest, hero_digest, logo_digest]
      expect(digests.uniq.length).to eq(4)
    end

    it 'registers all processed assets as static files' do
      # Count static files that match our digested pattern
      digested_files = site.static_files.select do |file|
        file.name.match?(/.*-[a-f0-9]{32}\.(css|js|jpg|png|svg|woff)$/)
      end

      # Should have at least 6 digested files (our original assets)
      expect(digested_files.length).to be >= 6

      # Check specific file types are present
      css_files = digested_files.select { |f| f.name.end_with?('.css') }
      js_files = digested_files.select { |f| f.name.end_with?('.js') }
      image_files = digested_files.select { |f| f.name.match?(/\.(jpg|png|svg)$/) }
      font_files = digested_files.select { |f| f.name.end_with?('.woff') }

      expect(css_files.length).to be >= 1
      expect(js_files.length).to be >= 1
      expect(image_files.length).to be >= 3
      expect(font_files.length).to be >= 1
    end
  end

  describe 'mixed assets with image transformations' do
    it 'handles both regular assets and image transformations' do
      # Create assets
      create_test_image(site, 'assets/hero.jpg', 1200, 800)
      create_test_css(site, 'assets/styles.css')
      create_test_js(site, 'assets/app.js')

      skyhook.process_assets

      # Use regular asset tag for CSS/JS
      css_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/styles.css')
      js_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/app.js')

      css_result = css_tag.render(context)
      js_result = js_tag.render(context)

      # Use image transformation for responsive image
      transform_tag = create_tag(Jekyll::Tags::ImageTransformTag, 'assets/hero.jpg[width="800"][format="webp"]')
      transform_result = transform_tag.render(context)

      # Use srcset for responsive images
      srcset_tag = create_tag(Jekyll::Tags::SrcsetTag, 'assets/hero.jpg[format="avif"] 400 800 1200')
      srcset_result = srcset_tag.render(context)

      # All should work together
      expect(css_result).to start_with('/_digested/assets/styles-')
      expect(js_result).to start_with('/_digested/assets/app-')
      expect(transform_result).to include('formatwebp-width800')
      expect(srcset_result).to include('formatavif-width400')
      expect(srcset_result).to include('formatavif-width800')
      expect(srcset_result).to include('formatavif-width1200')
    end

    it 'creates a realistic HTML page with all asset types' do
      # Set up assets
      create_test_image(site, 'assets/hero.jpg', 1200, 800)
      create_test_image(site, 'assets/logo.png', 200, 100)

      css_content = <<~CSS
        body {
          font-family: Arial, sans-serif;
          margin: 0;
        }
        .hero {
          background: url('../hero.jpg') center/cover;
          height: 400px;
        }
        .logo {
          background: url('../logo.png') no-repeat;
          width: 200px;
          height: 100px;
        }
      CSS
      create_test_css(site, 'assets/styles.css', css_content)
      create_test_js(site, 'assets/app.js')

      skyhook.process_assets

      # Simulate creating a complete HTML page
      html_parts = []

      # CSS link
      css_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/styles.css')
      css_href = css_tag.render(context)
      html_parts << "<link rel=\"stylesheet\" href=\"#{css_href}\">"

      # Responsive hero image
      avif_srcset = create_tag(Jekyll::Tags::SrcsetTag, 'assets/hero.jpg[format="avif"] 400 800 1200')
      webp_srcset = create_tag(Jekyll::Tags::SrcsetTag, 'assets/hero.jpg[format="webp"] 400 800 1200')
      png_srcset = create_tag(Jekyll::Tags::SrcsetTag, 'assets/hero.jpg 400 800 1200')
      fallback_img = create_tag(Jekyll::Tags::ImageTransformTag, 'assets/hero.jpg[width="800"]')

      html_parts << <<~HTML
        <picture>
          <source type="image/avif" #{avif_srcset.render(context)}>
          <source type="image/webp" #{webp_srcset.render(context)}>
          <img src="#{fallback_img.render(context)}" #{png_srcset.render(context)} alt="Hero">
        </picture>
      HTML

      # Logo image
      logo_tag = create_tag(Jekyll::Tags::ImageTransformTag, 'assets/logo.png[width="100"]')
      logo_src = logo_tag.render(context)
      html_parts << "<img src=\"#{logo_src}\" alt=\"Logo\" class=\"logo\">"

      # JavaScript
      js_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/app.js')
      js_src = js_tag.render(context)
      html_parts << "<script src=\"#{js_src}\"></script>"

      complete_html = html_parts.join("\n")

      # Verify all assets are properly referenced
      expect(complete_html).to include('/_digested/assets/styles-')
      expect(complete_html).to include('/_digested/assets/app-')
      expect(complete_html).to include('/_digested/assets/hero-')
      expect(complete_html).to include('/_digested/assets/logo-')
      expect(complete_html).to include('formatavif')
      expect(complete_html).to include('formatwebp')
      expect(complete_html).to include('width800')
      expect(complete_html).to include('width100')

      # No original asset paths should remain
      expect(complete_html).not_to include('assets/styles.css')
      expect(complete_html).not_to include('assets/app.js')
      expect(complete_html).not_to include('assets/hero.jpg')
      expect(complete_html).not_to include('assets/logo.png')
    end
  end

  describe 'asset dependency chain' do
    it 'handles CSS that references images that get transformed separately' do
      # Create image that will be referenced in CSS AND transformed separately
      create_test_image(site, 'assets/bg.jpg', 1600, 900)

      # CSS references the image
      css_content = <<~CSS
        .header {
          background: url('../bg.jpg') center/cover;
        }
      CSS
      create_test_css(site, 'assets/css/layout.css', css_content)

      skyhook.process_assets

      # Get the CSS with rewritten URLs
      css_tag = create_tag(Jekyll::Tags::AssetTag, 'assets/css/layout.css')
      css_path = css_tag.render(context)
      full_css_path = File.join(site.source, css_path[1..-1])
      css_content_processed = File.read(full_css_path)

      # Also transform the same image for responsive use
      responsive_tag = create_tag(Jekyll::Tags::ImageTransformTag, 'assets/bg.jpg[width="800"][format="webp"]')
      responsive_result = responsive_tag.render(context)

      # CSS should reference the original digested image
      expect(css_content_processed).to include('url(/_digested/assets/bg-')
      expect(css_content_processed).to include('.jpg)')

      # Responsive version should be separate
      expect(responsive_result).to include('formatwebp-width800')
      expect(responsive_result).to end_with('.webp')

      # Both should exist as separate files
      manifest_path = File.join(site.cache_dir, 'skyhook', 'assets-manifest.json')
      manifest = JSON.parse(File.read(manifest_path))

      expect(manifest.keys).to include('assets/bg.jpg') # Original
      expect(manifest.keys).to include('assets/bg.jpg#format=webp&width=800') # Transformed
    end
  end
end
