@use 'sass:map';
@use '@mezzanine-ui/system/palette' as palette;
@use '@mezzanine-ui/system/spacing' as spacing;
@use '@mezzanine-ui/system/typography' as typography;
@use '@mezzanine-ui/system/transition' as transition;
@use '@mezzanine-ui/system/radius' as radius;
@use '@mezzanine-ui/system/effect' as effect;
@use './table' as *;
@use '../button/utils' as button-utils;

$header-cell: (
  main: (
    typography: body-highlight,
    gap: spacing.semantic-variable(gap, tiny),
    padding: (
      horizontal: spacing.semantic-variable(padding, horizontal, comfort),
      vertical: spacing.semantic-variable(padding, vertical, base),
    ),
    help-size: spacing.semantic-variable(size, element, base-fixed),
    sort-size: spacing.semantic-variable(size, element, base-fixed),
    menu-size: spacing.semantic-variable(size, element, base-fixed),
    resize: (
      width: spacing.semantic-variable(size, element, hairline),
      height: spacing.semantic-variable(size, element, relaxed),
    ),
  ),
  sub: (
    typography: body-highlight,
    gap: spacing.semantic-variable(gap, tiny),
    padding: (
      horizontal: spacing.semantic-variable(padding, horizontal, comfort),
      vertical: spacing.semantic-variable(padding, vertical, base),
    ),
    help-size: spacing.semantic-variable(size, element, base-fixed),
    sort-size: spacing.semantic-variable(size, element, base-fixed),
    menu-size: spacing.semantic-variable(size, element, base-fixed),
    resize: (
      width: spacing.semantic-variable(size, element, hairline),
      height: spacing.semantic-variable(size, element, relaxed),
    ),
  ),
);

$content-cell: (
  main: (
    typography: body,
    padding: (
      horizontal: spacing.semantic-variable(padding, horizontal, comfort),
      vertical: spacing.semantic-variable(padding, vertical, calm),
    ),
  ),
  sub: (
    typography: body,
    padding: (
      horizontal: spacing.semantic-variable(padding, horizontal, comfort),
      vertical: spacing.semantic-variable(padding, vertical, base),
    ),
  ),
);

$icon-size: spacing.semantic-variable(size, element, base);
$action-height: spacing.semantic-variable(size, element, gentle);
$sticky-cell-z-index: 1;
$pagination-default-height: 0px;
$z-index-config: (
  sticky-cell-at-end: 1,
  sticky-cell-at-start: 2,
  header-sticky: 3,
  bulk-actions: 4,
  title-menu: 5,
);

@mixin text-color {
  color: palette.semantic-variable(text, neutral-solid);
}

@mixin surface-bg {
  background-color: palette.semantic-variable("background", base);
}

@mixin header-bg {
  background-color: palette.semantic-variable("background", neutral-ghost);
}

@mixin highlight-bg {
  background-color: palette.semantic-variable("background", neutral-faint);
}

@mixin active-bg {
  background-color: palette.semantic-variable("background", brand-ghost);
}

@mixin active-hover-bg {
  background-color: palette.semantic-variable("background", brand-subtle);
}

@mixin icon-size {
  width: $icon-size;
  height: $icon-size;
}

@mixin fixed-column-shadow($direction: 'start') {
  &::after {
    position: absolute;
    inset-block: 0;
    width: spacing.primitive-variable(10);
    content: '';
    pointer-events: none;
    transition: transition.standard(box-shadow);

    @if $direction == 'start' {
      inset-inline-end: 0;
      transform: translateX(100%);
    } @else {
      inset-inline-start: 0;
      transform: translateX(-100%);
    }
  }
}

@mixin fixed-column-shadow-active($direction: 'start') {
  &::after {
    @if $direction == 'start' {
      box-shadow: inset 8px 0 8px -8px palette.semantic-variable(shadow, dark-light);
    } @else {
      box-shadow: inset -8px 0 8px -8px palette.semantic-variable(shadow, dark-light);
    }
  }
}

.#{$prefix}-host {
  --mzn-table-pagination-height: #{$pagination-default-height};
  --mzn-table-title-menu-z-index: #{map.get($z-index-config, title-menu)};

  box-sizing: border-box;
  width: 100%;
  position: relative;

  * {
    box-sizing: border-box;
  }
}

.#{$prefix} {
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;

  @include text-color;
  @include surface-bg;

  th,
  td {
    border-bottom: 1px solid palette.semantic-variable(separator, neutral-faint);
  }

  &--sticky {
    thead {
      position: sticky;
      top: 0;
      z-index: #{map.get($z-index-config, header-sticky)};
    }
  }

  &--main {
    th {
      @include typography.semantic-variable(map.get($header-cell, main, typography));

      padding: map.get($header-cell, main, padding, vertical) map.get($header-cell, main, padding, horizontal);
      gap: map.get($header-cell, main, gap);
    }

    td {
      @include typography.semantic-variable(map.get($content-cell, main, typography));

      padding: 0 map.get($content-cell, main, padding, horizontal);
    }

    .#{$resize-handle-prefix} {
      --mzn-table-resize-handle-width: #{map.get($header-cell, main, resize, width)};
      --mzn-table-resize-handle-height: #{map.get($header-cell, main, resize, height)};
    }
  }

  &--sub {
    th {
      @include typography.semantic-variable(map.get($header-cell, sub, typography));

      padding: map.get($header-cell, sub, padding, vertical) map.get($header-cell, sub, padding, horizontal);
      gap: map.get($header-cell, sub, gap);
    }

    td {
      @include typography.semantic-variable(map.get($content-cell, sub, typography));

      padding: 0 map.get($content-cell, sub, padding, horizontal);
    }

    .#{$resize-handle-prefix} {
      --mzn-table-resize-handle-width: #{map.get($header-cell, sub, resize, width)};
      --mzn-table-resize-handle-height: #{map.get($header-cell, sub, resize, height)};
    }
  }

  // Loading state
  &--loading {
    pointer-events: none;
    opacity: 0.6;
  }
}

.#{$header-prefix} {
  @include header-bg;

  &__cell {
    position: relative;
    box-sizing: border-box;
    text-align: start;
    vertical-align: middle;

    @include header-bg;

    &--fixed {
      position: sticky;
      z-index: 2;

      @include header-bg;
    }
  }

  &__cell-content {
    width: 100%;
    display: flex;
    flex-flow: row;
    align-items: center;
    justify-content: space-between;
  }

  &__cell-actions {
    flex: 1;
    display: flex;
    flex-flow: row;
    gap: spacing.semantic-variable(gap, tiny);
    align-items: center;
    justify-content: flex-start;
  }

  &__cell-title {
    @include typography.overflow-ellipsis();

    color: palette.semantic-variable(text, neutral-strong);
  }

  &__cell-icon {
    border: none;
    border-radius: radius.variable(base);
    width: spacing.semantic-variable(size, element, base);
    height: spacing.semantic-variable(size, element, base);
    color: palette.semantic-variable(icon, neutral-light);
    transition: transition.standard(color, fast);

    &:hover {
      color: palette.semantic-variable(icon, neutral-bold);
    }

    &:focus-visible {
      outline: none;
      box-shadow: effect.variable(focus, primary);
    }
  }
}

.#{$body-prefix} {
  &__virtual-container {
    position: relative;
    width: 100%;
  }

  &__row {
    @include surface-bg();

    &--highlight {
      td {
        @include highlight-bg;
      }
    }

    &--selected {
      td {
        @include active-bg();
      }

      &:hover,
      &.#{$body-prefix}__row--highlight {
        td {
          @include active-hover-bg();
        }
      }
    }

    &--dragging {
      filter: drop-shadow(0 4px 20px palette.semantic-variable(shadow, dark));
      width: 100%;
      display: flex;
      align-items: center;
      border-bottom: 1px solid palette.semantic-variable(separator, neutral-faint);

      td {
        border-bottom: none;
      }
    }

    &--adding {
      td {
        @include active-bg;

        transition: transition.entrance(background-color, fast);
      }
    }

    &--deleting {
      td {
        background-color: palette.semantic-variable("background", error-ghost);
      }
    }

    &--fading-out {
      opacity: 0;
      transition: transition.exit(opacity, fast);

      td {
        background-color: palette.semantic-variable("background", error-ghost);
      }
    }

    &--separator {
      td {
        // allow-hardcoded: separator row border 3px visual emphasis, thicker than the 1px cell borders; no token for border-width > 1px
        border-bottom: 3px solid palette.semantic-variable("background", neutral-subtle);
      }
    }

    &--state-added {
      td {
        background-color: palette.semantic-variable("background", brand-ghost);
      }
    }

    &--state-deleted {
      td {
        background-color: palette.semantic-variable("background", error-ghost);
      }
    }

    &--state-disabled {
      td {
        background-color: palette.semantic-variable("background", neutral-subtle);
      }
    }

    &--zebra {
      td {
        background-color: palette.semantic-variable("background", neutral-ghost);
      }

      &.#{$body-prefix}__row--highlight {
        td {
          @include highlight-bg;
        }
      }

      &.#{$body-prefix}__row--selected {
        td {
          @include active-bg();
        }

        &:hover,
        &.#{$body-prefix}__row--highlight {
          td {
            @include active-hover-bg();
          }
        }
      }
    }
  }

  &__cell {
    text-align: start;
    vertical-align: middle;
  }
}

.#{$cell-prefix} {
  @include surface-bg();

  &--ellipsis {
    @include typography.overflow-ellipsis();
  }

  &--align-start {
    justify-content: flex-start;
    text-align: start;
  }

  &--align-center {
    justify-content: center;
    text-align: center;
  }

  &--align-end {
    justify-content: flex-end;
    text-align: end;
  }

  &--highlight {
    @include highlight-bg();
  }

  &--fixed {
    position: sticky;
  }

  &--fixed-start {
    inset-inline-start: var(--fixed-start-offset, 0);
    z-index: #{map.get($z-index-config, sticky-cell-at-start)};

    @include fixed-column-shadow('start');
  }

  &--fixed-end {
    inset-inline-end: var(--fixed-end-offset, 0);
    z-index: #{map.get($z-index-config, sticky-cell-at-end)};

    @include fixed-column-shadow('end');
  }

  &--fixed-shadow {
    @include fixed-column-shadow-active('start');
  }

  &--fixed-end#{&}--fixed-shadow {
    @include fixed-column-shadow-active('end');
  }

  &__content {
    display: block;
    word-break: break-all;
  }

  &__actions {
    display: inline-flex;
    align-items: center;
    gap: spacing.semantic-variable(gap, base);
  }
}

.#{$prefix}__drag-or-pin-handle-cell {
  text-align: center;
  vertical-align: middle;
}

.#{$prefix}__drag-or-pin-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: grab;

  &:active {
    cursor: grabbing;
  }
}

.#{$prefix}__pin-handle-icon {
  @include button-utils.reset();

  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;

  &:active {
    cursor: pointer;
  }
}

.#{$prefix}__collect-handle-icon {
  @include button-utils.reset();

  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;

  &--disabled {
    cursor: not-allowed;
    opacity: 0.5;
  }
}

.#{$prefix}__selection-checkbox {
  height: $action-height;
  display: flex;
  align-items: center;
  justify-content: center;
}

.#{$prefix}__expand-cell {
  text-align: center;
  vertical-align: middle;
}

.#{$prefix}__expand-icon {
  @include button-utils.reset();

  width: 100%;
  height: $action-height;
  display: flex;
  align-items: center;
  justify-content: center;
  color: palette.semantic-variable(icon, neutral-strong);
  transition: transition.entrance(transform, moderate);

  &--expanded {
    transform: rotate(90deg);
  }
}

.#{$prefix}__expanded-row {
  & > &__cell {
    background-color: palette.semantic-variable("background", neutral-ghost);
    padding: spacing.semantic-variable(padding, vertical, calm) spacing.semantic-variable(padding, horizontal, base-fixed);
  }

  &--adding {
    & > .#{$prefix}__expanded-row__cell {
      background-color: palette.semantic-variable("background", brand-ghost);
      transition: transition.entrance(background-color, fast);
    }
  }

  &--deleting {
    & > .#{$prefix}__expanded-row__cell {
      background-color: palette.semantic-variable("background", error-ghost);
    }
  }

  &--fading-out {
    opacity: 0;
    transition: transition.exit(opacity, fast);

    & > .#{$prefix}__expanded-row__cell {
      background-color: palette.semantic-variable("background", error-ghost);
    }
  }
}

.#{$prefix}__expanded-content {
  width: 100%;
}

.#{$prefix}__sort-icons {
  width: spacing.semantic-variable(size, element, base);
  height: spacing.semantic-variable(size, element, base);
  border: none;
  border-radius: radius.variable(base);
  background-color: transparent;
  padding: 0;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  gap: 0;
  align-items: center;
  justify-content: center;
  cursor: pointer;

  &:hover {
    & > .#{$prefix}__sort-icon {
      color: palette.semantic-variable(icon, neutral-bold);
    }
  }

  &:focus-visible {
    outline: none;
    box-shadow: effect.variable(focus, primary);
  }
}

.#{$prefix}__sort-icon {
  color: palette.semantic-variable(icon, neutral-light);
  transition: transition.standard(color, fast);

  &--active {
    color: palette.semantic-variable(icon, neutral-bold);
  }
}

.#{$resize-handle-prefix} {
  position: absolute;
  right: 0;
  top: 50%;
  z-index: 1;
  height: 100%;
  padding: 0 spacing.semantic-variable(padding, horizontal, comfort);
  cursor: col-resize;
  user-select: none;
  transform: translate3d(50%, -50%, 0);
  transition: transition.standard(background-color);

  &::after {
    content: '';
    position: absolute;
    right: 50%;
    top: 50%;
    z-index: 1;
    transform: translate3d(50%, -50%, 0);
    width: var(--mzn-table-resize-handle-width);
    height: var(--mzn-table-resize-handle-height);
    border-radius: radius.variable(full);
    background-color: palette.semantic-variable(separator, neutral-faint);
    transition: transition.standard(background-color);
  }

  &:hover {
    &::after {
      background-color: palette.semantic-variable("background", brand);
    }
  }
}

.#{$prefix}__empty {
  // allow-hardcoded: empty-state min-height 200px guarantees a consistent body height regardless of row count; not in primitive scale
  min-height: 200px;
  text-align: center;
  vertical-align: middle;
}

.#{$prefix}__bulk-actions {
  position: absolute;
  z-index: #{map.get($z-index-config, bulk-actions)};
  left: 50%;
  bottom: calc(#{spacing.semantic-variable(padding, vertical, relaxed)} + var(--mzn-table-pagination-height));
  transform: translateX(-50%);
  max-width: spacing.semantic-variable(size, container, xwide);
  padding: spacing.semantic-variable(padding, vertical, tight) spacing.semantic-variable(padding, horizontal, base);
  border-radius: radius.variable(roomy);
  background-color: palette.semantic-variable("background", fixed-solid);
  box-shadow: effect.variable(shadow, dark);
  display: flex;
  flex-flow: row;
  align-items: center;
  gap: spacing.semantic-variable(gap, spacious);

  &--fixed {
    position: fixed;
    bottom: spacing.semantic-variable(padding, vertical, relaxed);
    left: var(--mzn-bulk-actions-fixed-left, 50%);
    max-width: spacing.semantic-variable(size, container, xwide);
  }

  &__selection-summary {
    width: auto;
    height: 100%;
  }

  &__action-area {
    display: flex;
    flex-flow: row;
    align-items: center;
    gap: spacing.semantic-variable(gap, base);
  }

  &__separator {
    width: spacing.semantic-variable(size, element, hairline);
    height: spacing.semantic-variable(size, element, base);
    background-color: palette.semantic-variable(separator, neutral);
  }
}

/* ------------------------------------------------------------------ *
 * Angular CDK drag-drop integration                                   *
 *                                                                     *
 * Angular `MznTable` wires CDK's `cdkDropList` + `cdkDrag` on         *
 * `<tbody>`/`<tr>`. CDK ships no CSS — it only applies marker         *
 * classes (`.cdk-drag-placeholder`, `.cdk-drag-animating`,            *
 * `.cdk-drop-list-dragging`) and expects consumers to style them to   *
 * match `@hello-pangea/dnd`'s behaviour on the React side: the        *
 * source row becomes an invisible space-reserving placeholder while   *
 * sibling rows slide to reveal the drop target.                       *
 *                                                                     *
 * Rules are scoped inside `.#{$prefix}` so they only affect           *
 * Mezzanine tables. React never emits these classes, so the block    *
 * is a no-op there.                                                   *
 * ------------------------------------------------------------------ */
.#{$prefix} {
  /* Source row while dragging — hide so only the preview is visible. */
  .cdk-drag-placeholder {
    opacity: 0;
  }

  /* Sibling rows transition smoothly as the preview passes by. */
  &__body.cdk-drop-list-dragging .cdk-drag:not(.cdk-drag-placeholder) {
    transition: transition.standard(transform, moderate);
  }

  /* Ease the drop-settle animation when the user releases. */
  .cdk-drag-animating {
    transition: transition.standard(transform, moderate);
  }
}
