@use 'sass:map';
@use 'sass:list';
@use 'sass:color';
@use '../style/theming';

// MARK: Variables
$button-spacer-width: var(--dbx-padding-2);
$big-button-height: 46px; // 33% bigger

// MARK: Mixin
@mixin core() {
  // increases the height of the mat-mdc-button via Material's container-height tokens
  /// @dbx-utility button-big
  /// @intent enlarge the inner `mat-mdc-button` height to 46px (33% taller than default) by setting Material's `--mat-button-*-container-height` tokens
  /// @role layout
  /// @see-also button-wide
  .dbx-button-big,
  .dbx-button-large {
    --mat-button-text-container-height: var(--dbx-button-big-height, #{$big-button-height});
    --mat-button-filled-container-height: var(--dbx-button-big-height, #{$big-button-height});
    --mat-button-protected-container-height: var(--dbx-button-big-height, #{$big-button-height});
    --mat-button-outlined-container-height: var(--dbx-button-big-height, #{$big-button-height});
    --mat-button-tonal-container-height: var(--dbx-button-big-height, #{$big-button-height});
  }

  /// @dbx-utility button-form-field-height
  /// @intent match the inner `mat-mdc-button` height to `--mat-form-field-container-height` so a button aligns vertically with an adjacent form field
  /// @role layout
  /// @see-also button-big
  .dbx-button-form-field-height {
    --mat-button-text-container-height: var(--mat-form-field-container-height);
    --mat-button-filled-container-height: var(--mat-form-field-container-height);
    --mat-button-protected-container-height: var(--mat-form-field-container-height);
    --mat-button-outlined-container-height: var(--mat-form-field-container-height);
    --mat-button-tonal-container-height: var(--mat-form-field-container-height);
  }

  // Neutral hover/pressed/focus state layer instead of the primary-colored default.
  // Apply to buttons with custom background colors where the primary tint looks wrong.
  /// @dbx-utility button-neutral-interaction-color
  /// @intent neutralize Material's hover/pressed/focus/ripple state layer to `--mat-sys-on-surface` — use on buttons with a custom background where the primary-tinted state-layer would clash
  /// @role state
  .dbx-button-neutral-interaction-color {
    .mdc-button,
    &.mdc-button {
      $neutral: var(--mat-sys-on-surface, #000);

      --mat-button-text-state-layer-color: #{$neutral};
      --mat-button-text-pressed-state-layer-color: #{$neutral};
      --mat-button-text-focus-state-layer-color: #{$neutral};
      --mat-button-text-ripple-color: color-mix(in srgb, #{$neutral} 12%, transparent);
      --mat-button-protected-state-layer-color: #{$neutral};
      --mat-button-protected-pressed-state-layer-color: #{$neutral};
      --mat-button-protected-focus-state-layer-color: #{$neutral};
      --mat-button-protected-ripple-color: color-mix(in srgb, #{$neutral} 12%, transparent);
      --mat-button-outlined-state-layer-color: #{$neutral};
      --mat-button-outlined-pressed-state-layer-color: #{$neutral};
      --mat-button-outlined-focus-state-layer-color: #{$neutral};
      --mat-button-filled-state-layer-color: #{$neutral};
      --mat-button-filled-pressed-state-layer-color: #{$neutral};
      --mat-button-filled-focus-state-layer-color: #{$neutral};
    }
  }

  /// @dbx-utility button-wide
  /// @intent stretch the inner `.dbx-button` to a 120px minimum width (still capped by parent)
  /// @role layout
  /// @see-also button-grow
  .dbx-button-wide {
    .dbx-button {
      min-width: var(--dbx-button-wide-min-width, 120px);
      max-width: 100%;
    }
  }

  /// @dbx-utility button-wrap-group
  /// @intent group of buttons that wrap onto multiple rows — adds 6px right + bottom spacing between `<dbx-button>` / `<dbx-anchor>` / `<button>` / `<dbx-icon-button>` siblings
  /// @role layout
  /// @see-also button-column, dbx-flex-bar
  .dbx-button-wrap-group {
    > dbx-button,
    > dbx-anchor {
      display: inline-block;
      padding: 0 var(--dbx-padding-2) var(--dbx-padding-2) 0;
    }

    > button,
    > dbx-icon-button {
      margin: 0 var(--dbx-padding-2) var(--dbx-padding-2) 0;
    }
  }

  dbx-button.dbx-w100,
  dbx-button.dbx-button-wide {
    // when using dbx-w100 with dbx-button, make the button full width
    .dbx-button {
      width: 100%;
    }
  }

  /// @dbx-utility button-icon-tile
  /// @intent turn a `<dbx-button>` that wraps a `<dbx-icon-tile>` into a clickable tile — strips the button's padding/min-width so it hugs the tile, adopts the tile's `--dbx-icon-tile-border-radius`, and lifts a neutralized (`--mat-sys-on-surface`) state layer above the tile so hover/press/ripple reads on every color variant (including opaque full-color and primary-tonal tiles)
  /// @role layout
  /// @see-also icon-tile, button-neutral-interaction-color
  /// @anti-use don't apply to a `<dbx-button>` with no inner `<dbx-icon-tile>` — there is no tile surface to shape the button to or to overlay
  .dbx-button-icon-tile {
    .mat-mdc-button.dbx-base-button {
      border-radius: var(--dbx-icon-tile-border-radius, var(--mat-button-text-container-shape, var(--mat-sys-corner-full)));
      padding: 0;
      min-height: 0;
      min-width: 0;

      // Neutralize the interaction color so hover/press/ripple reads as a consistent
      // darkening regardless of the tile's dbxColor. Without this the state layer keeps
      // the default primary color, which is invisible on a primary-tonal tile.
      $neutral: var(--mat-sys-on-surface, #000);

      --mat-button-text-state-layer-color: #{$neutral};
      --mat-button-text-pressed-state-layer-color: #{$neutral};
      --mat-button-text-focus-state-layer-color: #{$neutral};
      --mat-button-text-ripple-color: color-mix(in srgb, #{$neutral} 12%, transparent);
    }

    // The tile's background lives inside .mdc-button__label (z-index: 1), which would
    // otherwise paint over the button's state layer / ripple — fully occluding it on an
    // opaque (full-color) tile and washing it out on a tonal one. Lift the ripple above
    // the label so the interaction feedback overlays the tile on every variant.
    .mat-mdc-button-persistent-ripple,
    .mat-mdc-button-ripple {
      z-index: 2;
    }
  }

  .dbx-icon-button .mat-mdc-button .mdc-button__label {
    display: flex;
    align-items: center;
  }

  .dbx-button-text-option-button {
    .dbx-button {
      margin-bottom: var(--dbx-padding-2);
    }

    .dbx-base-button .mdc-button__label {
      padding: 8px 0;
    }
  }

  /// @dbx-utility grow-button
  /// @intent stretch the `<dbx-button>` (and its inner `.dbx-button`) to the full width of its parent
  /// @role layout
  /// @see-also button-wide, dbx-w100
  .dbx-grow-button {
    width: 100%;

    .dbx-button {
      width: 100%;
    }
  }

  /// @dbx-utility button-spacer
  /// @intent right-padding spacer between buttons or beside a button — 6px right padding (use `<dbx-button-spacer>` to insert one inline)
  /// @role spacing
  /// @see-also chip-spacer, icon-spacer
  .dbx-button-spacer {
    padding-right: $button-spacer-width;
  }

  .mat-icon-button.dbx-button-spacer {
    margin-right: $button-spacer-width;
  }

  /// @dbx-utility button-column
  /// @intent vertical button stack — flex column with 6px bottom spacing between children, left-aligned by default (compose with `.dbx-button-column-center` to center)
  /// @role flex
  /// @see-also button-wrap-group, dbx-flex-column
  .dbx-button-column {
    display: flex;
    flex-direction: column;
    align-items: flex-start;

    > * {
      margin-bottom: var(--dbx-padding-2) !important;
    }
  }

  .dbx-button-column.dbx-button-column-center {
    align-items: center;
    justify-items: center;
  }

  // Floating buttons. Applied by `[dbxButtonFloating]`, or usable directly. The host floats
  // over the content — sticky (default) pins it to its scroll container's edge while its
  // parent section is on screen; `.dbx-button-floating-fixed` pins it to the viewport.
  // Offsets read `--dbx-button-floating-offset-x` / `-y` (set by the directive's offset
  // inputs), falling back to the shared `--dbx-button-floating-offset`, then `padding-4`.
  $button-floating-offset: var(--dbx-button-floating-offset, var(--dbx-padding-4));
  $button-floating-offset-x: var(--dbx-button-floating-offset-x, #{$button-floating-offset});
  $button-floating-offset-y: var(--dbx-button-floating-offset-y, #{$button-floating-offset});

  /// @dbx-utility button-floating
  /// @intent float a button (or a wrapper holding several buttons) over the content with `position: sticky` — pinned `offset-y` from the bottom of its scroll container while its parent section is on screen, right-aligned by default. Raised buttons get FAB-level elevation. Compose with `.dbx-button-floating-top` / `-left` / `-center` to reposition, or `.dbx-button-floating-fixed` to pin to the viewport. Sticky breaks when an ancestor between the host and the scroller sets `overflow`. Tune with `--dbx-button-floating-offset` (or `-offset-x` / `-offset-y`) and `--dbx-button-floating-z-index`
  /// @role layout
  /// @see-also button-floating-fixed, button-floating-top, button-floating-left, button-floating-center, content-pit-floating-button
  .dbx-button-floating {
    position: sticky;
    z-index: var(--dbx-button-floating-z-index, 10);
    bottom: $button-floating-offset-y;
    display: flex;
    gap: var(--dbx-padding-2);
    width: fit-content;
    margin-left: auto;

    // FAB-level elevation for raised buttons so they read as floating above the content
    --mat-button-protected-container-elevation-shadow: var(--mat-sys-level3);
    --mat-button-protected-focus-container-elevation-shadow: var(--mat-sys-level3);
    --mat-button-protected-pressed-container-elevation-shadow: var(--mat-sys-level3);
    --mat-button-protected-hover-container-elevation-shadow: var(--mat-sys-level4);
  }

  /// @dbx-utility button-floating-fixed
  /// @intent pin a `.dbx-button-floating` to the viewport with `position: fixed` — a classic floating action button, `offset-x` / `offset-y` from the bottom-right corner by default (composes with `-top` / `-left` / `-center`). Breaks when an ancestor sets `transform`, `filter` or `contain`, which re-anchors fixed positioning to that ancestor
  /// @role layout
  /// @parent button-floating
  /// @see-also button-floating, button-floating-top, button-floating-left, button-floating-center
  .dbx-button-floating-fixed {
    position: fixed;
    margin: 0;
    right: $button-floating-offset-x;
    bottom: $button-floating-offset-y;
  }

  // The position modifiers below are declared after the base + fixed rules so they win at equal specificity.

  /// @dbx-utility button-floating-top
  /// @intent pin a `.dbx-button-floating` to the top edge (`offset-y` from the top) instead of the bottom — in sticky mode place the host at the start of its section
  /// @role layout
  /// @parent button-floating
  /// @see-also button-floating, button-floating-left, button-floating-center
  .dbx-button-floating-top {
    top: $button-floating-offset-y;
    bottom: auto;
  }

  /// @dbx-utility button-floating-left
  /// @intent align a `.dbx-button-floating` to the left edge instead of the right
  /// @role layout
  /// @parent button-floating
  /// @see-also button-floating, button-floating-top, button-floating-center
  .dbx-button-floating-left {
    margin-left: 0;
    margin-right: auto;

    &.dbx-button-floating-fixed {
      left: $button-floating-offset-x;
      right: auto;
    }
  }

  /// @dbx-utility button-floating-center
  /// @intent horizontally center a `.dbx-button-floating` instead of right-aligning it
  /// @role layout
  /// @parent button-floating
  /// @see-also button-floating, button-floating-top, button-floating-left
  .dbx-button-floating-center {
    margin-left: auto;
    margin-right: auto;

    &.dbx-button-floating-fixed {
      left: 50%;
      right: auto;
      transform: translateX(-50%);
    }
  }

  // dbx-color interactions
  // `DbxColorDirective` is a pure token provider — it sets `--dbx-bg-color-current` /
  // `--dbx-color-current` and adds the `.dbx-color` marker, but never paints the
  // host itself; the named `.dbx-{color}-bg` classes it applies are token-only too.
  // `<dbx-button>` hosts the directive (via `hostDirectives`) and pushes its
  // resolved color (active echo > `color` input > `buttonStyle.color`) into it —
  // so use the button's `color` input, never `[dbxColor]`, on a `dbx-button`. The
  // standalone `<dbx-progress-spinner-button>` / `<dbx-progress-bar-button>` take
  // `[dbxColor]` directly. The rules below map the host tokens onto the Material
  // button vars per variant on the inner `.mdc-button.dbx-base-button`. Scoped on
  // the host marker so a button inside a `[dbxColor]` section doesn't repaint from
  // inherited tokens — only a directly-colored button host reacts. `:not(.dbx-default)`
  // guard: the host directive always adds the `.dbx-color` marker, so an uncolored
  // button (marked `dbx-default`) keeps native Material styling. `buttonColor` on
  // `DbxProgressButtonConfig` was removed.
  $color-value: theming.$dbx-bg-color;
  $contrast-value: theming.$dbx-color;

  dbx-button.dbx-color:not(.dbx-default),
  dbx-progress-spinner-button.dbx-color:not(.dbx-default),
  dbx-spinner-button.dbx-color:not(.dbx-default),
  dbx-progress-bar-button.dbx-color:not(.dbx-default),
  dbx-bar-button.dbx-color:not(.dbx-default) {
    .mdc-button.dbx-base-button {
      // text/basic buttons
      background: none;
      --mat-button-text-label-text-color: #{$color-value};
      --mat-button-text-ripple-color: color-mix(in srgb, #{$color-value} 12%, transparent);
      --mat-button-text-state-layer-color: #{$color-value};
      --mat-progress-spinner-active-indicator-color: #{$color-value};

      .mat-mdc-progress-bar {
        --mat-progress-bar-active-indicator-color: #{$color-value};
      }

      // raised buttons
      &.mat-mdc-raised-button {
        background: var(--mat-button-protected-container-color);

        --mat-button-protected-container-color: #{$color-value};
        --mat-button-protected-label-text-color: #{$contrast-value};
        --mat-button-protected-state-layer-color: #{$contrast-value};
        --mat-button-protected-ripple-color: color-mix(in srgb, #{$contrast-value} 12%, transparent);

        &.mat-mdc-button-disabled {
          background-color: var(--mat-button-protected-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent));
        }
      }

      // stroked/outlined buttons
      &.mat-mdc-outlined-button {
        --mat-button-outlined-container-color: #{$contrast-value};
        --mat-button-outlined-label-text-color: #{$color-value};
        --mat-button-outlined-state-layer-color: #{$color-value};
        --mat-button-outlined-ripple-color: color-mix(in srgb, #{$color-value} 12%, transparent);

        --mat-progress-spinner-active-indicator-color: #{$color-value};
      }

      // flat buttons
      &.mat-mdc-unelevated-button {
        background: var(--mat-button-filled-container-color);

        --mat-button-filled-container-color: #{$color-value};
        --mat-button-filled-label-text-color: #{$contrast-value};
        --mat-button-filled-state-layer-color: #{$contrast-value};
        --mat-button-filled-ripple-color: color-mix(in srgb, #{$contrast-value} 12%, transparent);

        &.mat-mdc-button-disabled {
          background-color: var(--mat-button-protected-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent));
        }
      }

      // icon buttons
      &.mat-mdc-icon-button {
        background: none;

        --mat-icon-button-icon-color: var(--dbx-button-icon-color, #{$color-value});
        --mat-icon-button-ripple-color: color-mix(in srgb, #{$color-value} 12%, transparent);
        --mat-icon-button-state-layer-color: #{$color-value};
      }

      // tonal buttons
      &.mat-mdc-tonal-button {
        background: rgb(from #{$color-value} r g b / calc(alpha * 0.12));

        --mat-button-tonal-container-color: color-mix(in srgb, #{$color-value} 12%, transparent);
        --mat-button-tonal-label-text-color: #{$contrast-value};
        --mat-button-tonal-ripple-color: color-mix(in srgb, #{$contrast-value} 12%, transparent);
        --mat-button-tonal-state-layer-color: #{$contrast-value};
      }
    }

    // FABs / extended FABs (`fab` without `iconOnly` renders mat-fab, which reads the --mat-fab-* tokens)
    .mat-mdc-fab-base.dbx-base-button {
      --mat-fab-container-color: #{$color-value};
      --mat-fab-foreground-color: #{$contrast-value};
      --mat-fab-state-layer-color: #{$contrast-value};
      --mat-fab-ripple-color: color-mix(in srgb, #{$contrast-value} 12%, transparent);
    }
  }

  .dbx-icon-button > .mat-mdc-button {
    background: inherit;
  }

  .dbx-icon-button.dbx-grey-bg {
    background: none;

    > .mat-mdc-button {
      background: #{theming.$dbx-grey-color-contrast};
    }
  }

  .dbx-icon-button.dbx-disabled-bg {
    background: none;

    > .mat-mdc-button {
      background: #{theming.$dbx-disabled-color-contrast};
    }
  }
}

@mixin theme($theme-config) {
}
