@use 'sass:map';
@use '../utils/constants.scss';
@use '../utils/mixins.scss' as mixins;
@use '../utils/tokens.scss' as tokens;
@use '../utils/stateLayerVars.scss' as state-layer;
@use '../utils/inputChoiceMixins.scss' as choiceMixins;

@import '@viasat/beam-tokens/components/Card';
@import '@viasat/beam-tokens/components/Input';

$cardBaseClass: '#{constants.$prefix}card';
$cardRadiusOuterVarName: '--#{constants.$prefix}card-radius-outer';
$selectionIndicatorTopVarName: '--#{constants.$prefix}card-selection-indicator-top';
$selectionIndicatorRightVarName: '--#{constants.$prefix}card-selection-indicator-right';

@mixin backdrop-overlay($color) {
  position: relative;

  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;

    background: $color;

    background-size: cover;
    background-repeat: no-repeat;
    z-index: 1;
    pointer-events: none;
  }
}

@mixin media-overlays {
  &__overlay-top,
  &__overlay-middle,
  &__overlay-bottom {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 2;
  }

  &__overlay-top {
    top: 0;
  }

  &__overlay-middle {
    top: 50%;
    transform: translateY(-50%);
  }

  &__overlay-bottom {
    bottom: 0;
  }
}

$cardDensity: (
  density-sm: (
    gap: tokens.$bm-comp-card-space-gap-sm,
    inset: tokens.$bm-comp-card-space-pad-sm,
  ),
  density-md: (
    gap: tokens.$bm-comp-card-space-gap-md,
    inset: tokens.$bm-comp-card-space-pad-md,
  ),
  density-lg: (
    gap: tokens.$bm-comp-card-space-gap-lg,
    inset: tokens.$bm-comp-card-space-pad-lg,
  ),
);

// Main Card component
.#{$cardBaseClass} {
  #{$cardRadiusOuterVarName}: #{tokens.$bm-comp-card-radius-outer};
  isolation: isolate;

  display: flex;
  flex-direction: column;
  outline: none;
  border-radius: var(#{$cardRadiusOuterVarName});

  &--default-background {
    background: tokens.$bm-comp-card-color-bg;
  }
  &--default-shadow {
    box-shadow: tokens.$bm-comp-card-shadow;
  }
  &--default-border {
    border-color: tokens.$bm-comp-card-color-border;
  }

  // Interactive card styles (clickable/selectable)
  &--interactive {
    position: relative;
    cursor: pointer;
    user-select: none;

    // Reset default button/anchor styles when using as those elements
    text-decoration: none;
    color: inherit;
    font: inherit;
    text-align: inherit;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding: 0;
    margin: 0;

    // State layer for hover/active states (direct child only, not nested state layers)
    // Extend to cover the border area so overlay matches full card surface
    > .#{state-layer.$stateLayerBaseClass} {
      pointer-events: none;
      z-index: 3;

      $border-offset: calc(0px - tokens.$bm-sem-border-width-md);
      #{state-layer.$top}: $border-offset;
      #{state-layer.$right}: $border-offset;
      #{state-layer.$bottom}: $border-offset;
      #{state-layer.$left}: $border-offset;

      // Adjust outline-offset to account for state layer's negative positioning
      // This ensures the focus ring appears at the correct distance from the card's outer edge
      #{state-layer.$outline-offset}: calc(
        tokens.$bm-sem-border-width-md + tokens.$bm-sem-size-focus-offset
      );
    }

    // Suppress state layer when hovering interactive children
    // Note: Excludes the card's own hidden input
    &:has(
        button:hover,
        a:hover,
        input:not([data-card-input]):hover,
        select:hover,
        textarea:hover,
        [role='button']:hover,
        [role='link']:hover,
        [tabindex]:not([tabindex='-1']):hover
      )
      > .#{state-layer.$stateLayerBaseClass} {
      #{state-layer.$opacity}: 0 !important;
      #{state-layer.$background}: transparent !important;
    }

    // Suppress state layer when clicking (active) interactive children
    // Note: Excludes the card's own hidden input 
    &:has(
        button:active,
        a:active,
        input:not([data-card-input]):active,
        select:active,
        textarea:active,
        [role='button']:active,
        [role='link']:active,
        [tabindex]:not([tabindex='-1']):active
      )
      > .#{state-layer.$stateLayerBaseClass} {
      #{state-layer.$opacity}: 0 !important;
      #{state-layer.$background}: transparent !important;
    }

    // Suppress state layer focus outline when interactive children have focus
    // Note: Excludes the card's own hidden input 
    &:has(
        button:focus-visible,
        a:focus-visible,
        input:not([data-card-input]):focus-visible,
        select:focus-visible,
        textarea:focus-visible,
        [role='button']:focus-visible,
        [role='link']:focus-visible,
        [tabindex]:not([tabindex='-1']):focus-visible
      )
      > .#{state-layer.$stateLayerBaseClass} {
      #{state-layer.$outline-color}: transparent !important;
    }
  }


  // Disabled state
  &--disabled {
    opacity: tokens.$bm-sem-opacity-disabled;
    cursor: not-allowed;
  }

  // Hidden input for selectable cards (provides accessibility and form integration)
  &__hidden-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 1; // Above card background, below content
    border: none;
    appearance: none;

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

  // Selectable card styles
  &--selectable {
    // Reserve space in header to prevent overlap with selection indicator
    // Only apply when card doesn't have media-above
    &:not(:has(.#{$cardBaseClass}__media-above)) .#{$cardBaseClass}__header::after {
      content: '';
      order: 999; // Position at end of flex container
      width: tokens.$bm-comp-input-size-choice-checkbox;
      flex-shrink: 0;
    }

    // Focus styles via :has() - show focus ring when hidden input is focused
    &:has(.#{$cardBaseClass}__hidden-input:focus-visible) > .#{state-layer.$stateLayerBaseClass} {
      #{state-layer.$outline-width}: tokens.$bm-sem-border-width-focus;
      #{state-layer.$outline-color}: tokens.$bm-sem-color-border-focus;
    }
  }

  // Card-specific selection indicator (visual-only, divorced from Checkbox/RadioButton components)
  &__selection-indicator {
    position: absolute;
    top: var(#{$selectionIndicatorTopVarName}, #{tokens.$bm-sem-space-100});
    right: var(#{$selectionIndicatorRightVarName}, #{tokens.$bm-sem-space-100});
    z-index: 4;
    pointer-events: none;
    display: block;

    // Checkbox variant
    &--checkbox {
      @include choiceMixins.choice-checkbox-base();
    }

    // Radio variant
    &--radio {
      @include choiceMixins.choice-radio-base();
    }

    // Checked state - checkbox
    &--checkbox#{&}--checked {
      @include choiceMixins.choice-checkbox-checked();
    }

    // Checked state - radio
    &--radio#{&}--checked {
      @include choiceMixins.choice-radio-checked();
    }

    // Disabled state
    &--disabled {
      border-color: tokens.$bm-comp-input-color-border-disabled;
      background-color: tokens.$bm-comp-input-color-bg-disabled;
    }

    &--checkbox#{&}--checked#{&}--disabled {
      background-color: tokens.$bm-comp-input-color-icon-disabled;
    }

    &--radio#{&}--checked#{&}--disabled::after {
      background-color: tokens.$bm-comp-input-color-icon-disabled;
    }
  }

  &--selected {
    border-color: tokens.$bm-comp-card-color-border-selected;

    outline: tokens.$bm-sem-border-width-selected
      solid tokens.$bm-comp-card-color-border-selected;
    outline-offset: calc(0px - tokens.$bm-sem-border-width-md);
  }

  // Density modifiers apply positioning for selection indicator and styling for content
  @each $density, $values in $cardDensity {
    &--#{$density} {
      #{$selectionIndicatorTopVarName}: #{map.get($values, inset)};
      #{$selectionIndicatorRightVarName}: #{map.get($values, inset)};

      > .#{$cardBaseClass}__content {
        gap: map.get($values, gap);
        padding: map.get($values, inset);
      }
    }
  }
}

// Card.Content - sits above hidden input for selectable cards
.#{$cardBaseClass}__content {
  display: flex;
  flex-direction: column;
  position: relative;
  z-index: 2;
}

// Card.Header
.#{$cardBaseClass}__header {
  display: flex;
  flex-direction: row;
  gap: tokens.$bm-comp-card-space-header-gap;
  position: relative;
  z-index: 2;

  &__content-before {
    order: 1;
    display: flex;
    gap: tokens.$bm-comp-card-space-header-actions-gap;
    color: tokens.$bm-comp-card-color-heading;
  }

  &__heading {
    order: 2;
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;

    font: tokens.$bm-comp-card-typo-heading;
    color: tokens.$bm-comp-card-color-heading;

    // ensure anything slotted will always come after Eyebrow, Text, Supporting text
    * {
      order: 999;
    }

    &__eyebrow {
      order: 0;
      display: flex;
      font: tokens.$bm-comp-card-typo-eyebrow;
      color: tokens.$bm-comp-card-color-eyebrow;
      gap: tokens.$bm-comp-card-space-header-actions-gap;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    &__text {
      order: 1;
      display: flex;
    }

    &__supporting-text {
      order: 2;
      display: flex;
      color: tokens.$bm-comp-card-color-supporting;
      font: tokens.$bm-comp-card-typo-supporting;
    }
  }

  &__content-after {
    order: 3;
    display: flex;
    padding-top: tokens.$bm-sem-space-12;
    justify-content: flex-end;
    align-items: flex-start;
    gap: tokens.$bm-comp-card-space-header-actions-gap;
    align-self: stretch;
    color: tokens.$bm-comp-card-color-icon;
  }
}

.#{$cardBaseClass}__media-above {
  // Calculate inner radius from outer: inner = outer - border-width
  $inner-radius: calc(var(#{$cardRadiusOuterVarName}) - #{tokens.$bm-sem-border-width-md});
  border-top-left-radius: $inner-radius;
  border-top-right-radius: $inner-radius;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;

  &:last-child {
    border-bottom-left-radius: $inner-radius;
    border-bottom-right-radius: $inner-radius;
  }
}

.#{$cardBaseClass}__media-below {
  border-radius: tokens.$bm-comp-card-radius-inner;
}

// Media sections sit above hidden input for selectable cards
.#{$cardBaseClass}__media-above,
.#{$cardBaseClass}__media-below {
  display: flex;
  overflow: hidden;
  width: 100%;
  isolation: isolate;
  position: relative;
  z-index: 2;

  @each $color in black, white {
    @each $opacity in 10, 20, 30, 40 {
      &--overlay-color-#{$color}-#{$opacity} {
        @include backdrop-overlay(
          var(--#{constants.$prefix}sem-color-overlay-#{$color}-#{$opacity})
        );
      }
    }
  }

  @include media-overlays;
}

// Card.Body
.#{$cardBaseClass}__body {
  display: flex;
  flex-direction: column;
  color: tokens.$bm-comp-card-color-body;
  font: tokens.$bm-comp-card-typo-body;
  gap: tokens.$bm-sem-space-100;
  position: relative;
  z-index: 2;
}

// Card.Footer
.#{$cardBaseClass}__footer {
  display: flex;
  gap: tokens.$bm-sem-space-50;
  flex-direction: column;
  position: relative;
  z-index: 2;

  &__actions {
    display: flex;
    padding-top: tokens.$bm-comp-card-space-footer-actions-top;
    gap: tokens.$bm-comp-card-space-footer-actions-gap;
    flex-shrink: 0;
    flex-wrap: wrap;
    align-items: center;
    align-content: center;

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

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

    &--spaceBetween {
      justify-content: space-between;
    }

    &--stacked {
      justify-content: center;
      flex-direction: column;
      gap: tokens.$bm-comp-card-space-footer-actions-gap-stacked;
    }
  }
}
