# frozen_string_literal: true

require "stylesheet/compiler"

RSpec.describe Stylesheet::Compiler do
  describe "compilation" do
    Dir["#{Rails.root.join("app/assets/stylesheets")}/*.scss"].each do |path|
      next if path =~ /ember_cli/

      path = File.basename(path, ".scss")

      it "can compile '#{path}' css" do
        css, _map = Stylesheet::Compiler.compile_asset(path)
        expect(css.length).to be > 500
      end
    end
  end

  context "with a theme" do
    let!(:theme) { Fabricate(:theme) }
    let!(:upload) do
      UploadCreator.new(file_from_fixtures("logo.png"), "logo.png").create_for(
        Discourse.system_user.id,
      )
    end
    let!(:upload_theme_field) do
      ThemeField.create!(
        theme: theme,
        target_id: 0,
        name: "primary",
        upload: upload,
        value: "",
        type_id: ThemeField.types[:theme_upload_var],
      )
    end
    let!(:stylesheet_theme_field) do
      ThemeField.create!(
        theme: theme,
        target_id: 0,
        name: "scss",
        value: "body { background: $primary }",
        type_id: ThemeField.types[:scss],
      )
    end
    before { stylesheet_theme_field.save! }

    it "theme stylesheet should be able to access theme asset variables" do
      css, _map =
        Stylesheet::Compiler.compile_asset(
          "desktop_theme",
          theme_id: theme.id,
          theme_variables: theme.scss_variables,
        )
      expect(css).to include(upload.url)
    end

    context "with a plugin" do
      let :plugin1 do
        plugin1 = plugin_from_fixtures("my_plugin")
        plugin1.register_css "body { background: $primary }"
        plugin1
      end

      let :plugin2 do
        plugin2 = plugin_from_fixtures("scss_plugin")
        plugin2
      end

      before do
        Discourse.plugins << plugin1
        Discourse.plugins << plugin2
        plugin1.activate!
        plugin2.activate!
        Stylesheet::Importer.register_imports!
      end

      after do
        Discourse.plugins.delete plugin1
        Discourse.plugins.delete plugin2
        Stylesheet::Importer.register_imports!
        DiscoursePluginRegistry.reset!
      end

      it "does not include theme variables in plugins" do
        css, _map = Stylesheet::Compiler.compile_asset("my_plugin", theme_id: theme.id)
        expect(css).not_to include(upload.url)
        expect(css).to include("background:")
      end

      context "with the `rtl` option" do
        it "generates an RTL version of the plugin CSS if the option is true" do
          css, _ = Stylesheet::Compiler.compile_asset("scss_plugin", theme_id: theme.id, rtl: true)
          expect(css).to include(".pull-left{float:right}")
          expect(css).not_to include(".pull-left{float:left}")
        end

        it "returns an unchanged version of the plugin CSS" do
          css, _ = Stylesheet::Compiler.compile_asset("scss_plugin", theme_id: theme.id, rtl: false)
          expect(css).to include(".pull-left{float:left}")
          expect(css).not_to include(".pull-left{float:right}")
        end
      end

      it "supports SCSS imports" do
        css, _map = Stylesheet::Compiler.compile_asset("scss_plugin", theme_id: theme.id)

        expect(css).to include("border-color:red")
        expect(css).to include("fill:green")
        expect(css).to include("line-height:1.2em")
        expect(css).to include("border-color:#c00")
      end
    end
  end

  it "supports absolute-image-url" do
    scss = Stylesheet::Importer.new({}).prepended_scss
    scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
    css, _map = Stylesheet::Compiler.compile(scss, "test.scss")

    expect(css).to include('url("http://test.localhost/images/favicons/github.png")')
    expect(css).not_to include("absolute-image-url")
  end

  it "supports absolute-image-url in subfolder" do
    set_subfolder "/subfo"
    scss = Stylesheet::Importer.new({}).prepended_scss
    scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
    css, _map = Stylesheet::Compiler.compile(scss, "test2.scss")

    expect(css).to include('url("http://test.localhost/subfo/images/favicons/github.png")')
    expect(css).not_to include("absolute-image-url")
  end

  it "supports absolute-image-url with CDNs" do
    set_cdn_url "https://awesome.com"
    scss = Stylesheet::Importer.new({}).prepended_scss
    scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
    css, _map = Stylesheet::Compiler.compile(scss, "test2.scss")

    expect(css).to include('url("https://awesome.com/images/favicons/github.png")')
    expect(css).not_to include("absolute-image-url")
  end

  it "supports absolute-image-url in plugins" do
    set_cdn_url "https://awesome.com"
    scss = Stylesheet::Importer.new({}).prepended_scss
    scss +=
      ".body{background-image: absolute-image-url('/plugins/discourse-special/images/somefile.png');}"
    css, _map = Stylesheet::Compiler.compile(scss, "discourse-special.scss")

    expect(css).to include(
      'url("https://awesome.com/plugins/discourse-special/images/somefile.png")',
    )
    expect(css).not_to include("absolute-image-url")
  end

  context "with a color scheme" do
    it "returns the default color definitions when no color scheme is specified" do
      css, _map = Stylesheet::Compiler.compile_asset("color_definitions")
      expect(css).to include("--header_background:")
      expect(css).to include("--primary:")
    end

    it "returns color definitions for a custom color scheme" do
      cs =
        Fabricate(
          :color_scheme,
          name: "Stylish",
          color_scheme_colors: [
            Fabricate(:color_scheme_color, name: "header_primary", hex: "88af8e"),
            Fabricate(:color_scheme_color, name: "header_background", hex: "f8745c"),
          ],
        )

      css, _map = Stylesheet::Compiler.compile_asset("color_definitions", color_scheme_id: cs.id)

      expect(css).to include("--header_background: #f8745c")
      expect(css).to include("--header_primary: #88af8e")
      expect(css).to include("--header_background-rgb: 248, 116, 92")
    end

    context "with a plugin" do
      before do
        plugin = plugin_from_fixtures("color_definition")
        Discourse.plugins << plugin
        plugin.activate!
      end

      after do
        Discourse.plugins.pop
        DiscoursePluginRegistry.reset!
      end

      it "includes color definitions from plugins" do
        css, _map = Stylesheet::Compiler.compile_asset("color_definitions")

        expect(css).to include("--plugin-color")
      end
    end
  end

  describe "indexes" do
    it "include all SCSS files in their respective folders" do
      refs = []

      Dir
        .glob(Rails.root.join("app/assets/stylesheets/**/*/"))
        .each do |dir|
          Dir
            .glob("#{dir}_index.scss")
            .each do |indexfile|
              contents = File.read indexfile

              files = Dir["#{dir}*.scss"]
              files -= Dir["#{dir}_index.scss"]
              files.each do |path|
                filename = File.basename(path, ".scss")
                if !contents.match(/@import "#{filename}";/)
                  refs << "#{filename} import missing in #{indexfile}"
                end
              end
            end
        end

      expect(refs).to eq([])
    end
  end

  describe ".compile" do
    it "produces RTL CSS when rtl option is given" do
      css, _ = Stylesheet::Compiler.compile("a{right:1px}", "test.scss", rtl: true)
      expect(css).to eq("a{left:1px}")
    end
  end
end