// Output tests for the `generate-utility` mixin from
// scss/mixins/bootstrap/_utilities.scss — the engine behind Tabler's utility
// classes. `@use "../mixins/bootstrap/utilities"` pulls in the real
// settings/variables chain, so `$enable-important-utilities` = true (hence the
// `!important` in the output). Custom properties are expected unprefixed: the
// `--tblr-` prefix is added later, by the css pipeline (.build/css-var-prefix.ts).
//
// Each `it` feeds the mixin a hand-built utility map and asserts the generated
// classes, covering the branches that shape the output: map vs list values,
// single vs multiple properties, custom class, css-var mode, pseudo-class
// states and the responsive infix.

@use 'sass:map';
@use '../mixins/bootstrap/utilities' as *;
@use '../mixins/bootstrap/breakpoints' as *;

@include describe('generate-utility') {
  @include it('generates a class per key from a values map') {
    @include assert() {
      @include output() {
        @include generate-utility(
          (
            property: opacity,
            values: (
              0: 0,
              50: 0.5,
            ),
          )
        );
      }
      @include expect() {
        .opacity-0 {
          opacity: 0 !important;
        }
        .opacity-50 {
          opacity: 0.5 !important;
        }
      }
    }
  }

  @include it('zips a plain list of values into key/value pairs') {
    @include assert() {
      @include output() {
        @include generate-utility(
          (
            property: float,
            class: float,
            values: (
              left,
              right,
            ),
          )
        );
      }
      @include expect() {
        .float-left {
          float: left !important;
        }
        .float-right {
          float: right !important;
        }
      }
    }
  }

  @include it('emits every property when several are given') {
    @include assert() {
      @include output() {
        @include generate-utility(
          (
            property: margin-inline-end margin-inline-start,
            class: mx,
            values: (
              0: 0,
              auto: auto,
            ),
          )
        );
      }
      @include expect() {
        .mx-0 {
          margin-inline-end: 0 !important;
          margin-inline-start: 0 !important;
        }
        .mx-auto {
          margin-inline-end: auto !important;
          margin-inline-start: auto !important;
        }
      }
    }
  }

  @include it('sets a custom property instead of a declaration in css-var mode') {
    @include assert() {
      @include output() {
        @include generate-utility(
          (
            property: opacity,
            class: opacity,
            css-var: true,
            values: (
              50: 0.5,
            ),
          )
        );
      }
      @include expect() {
        .opacity-50 {
          --opacity: 0.5;
        }
      }
    }
  }

  @include it('adds a pseudo-class variant for each declared state') {
    @include assert() {
      @include output() {
        @include generate-utility(
          (
            property: text-decoration,
            class: text-decoration,
            state: hover,
            values: (underline),
          )
        );
      }
      @include expect() {
        .text-decoration-underline {
          text-decoration: underline !important;
        }
        .text-decoration-underline-hover:hover {
          text-decoration: underline !important;
        }
      }
    }
  }

  @include it('injects the responsive infix into the class name') {
    @include assert() {
      @include output() {
        @include generate-utility(
          (
            property: display,
            class: d,
            values: (none),
          ),
          '-md'
        );
      }
      @include expect() {
        .d-md-none {
          display: none !important;
        }
      }
    }
  }
}

// `generate-utility` itself does not read the `responsive` key — that gate lives
// in bootstrap/utilities/_api.scss, which loops the breakpoints and only calls
// the mixin for a given infix when `map.get($utility, responsive)` is truthy (or
// it's the base, infix-less breakpoint). This reproduces that gate against a local
// breakpoint map with two utilities: one `responsive: true`, one without.
@include describe('generate-utility (responsive property)') {
  $g: (
    xs: 0,
    sm: 576px,
    md: 768px,
  );
  $utils: (
    'display': (
      property: display,
      class: d,
      responsive: true,
      values: (
        none,
        flex,
      ),
    ),
    'float': (
      property: float,
      class: float,
      values: (
        start: inline-start,
        end: inline-end,
        none: none,
      ),
    ),
  );

  @include it('only a `responsive: true` utility gets breakpoint-infixed variants') {
    @include assert() {
      @include output() {
        @each $bp in map.keys($g) {
          @include media-breakpoint-up($bp, $g) {
            $infix: breakpoint-infix($bp, $g);
            @each $key, $utility in $utils {
              @if map.get($utility, responsive) or $infix == '' {
                @include generate-utility($utility, $infix);
              }
            }
          }
        }
      }
      @include expect() {
        // base breakpoint: both utilities emit bare classes
        .d-none {
          display: none !important;
        }
        .d-flex {
          display: flex !important;
        }
        .float-start {
          float: inline-start !important;
        }
        .float-end {
          float: inline-end !important;
        }
        .float-none {
          float: none !important;
        }

        // responsive breakpoints: only `d` (responsive: true) is repeated; `float` is not
        @media (min-width: 576px) {
          .d-sm-none {
            display: none !important;
          }
          .d-sm-flex {
            display: flex !important;
          }
        }

        @media (min-width: 768px) {
          .d-md-none {
            display: none !important;
          }
          .d-md-flex {
            display: flex !important;
          }
        }
      }
    }
  }
}
