@use 'sass:map';
@use './../utils/tokens.scss' as tokens;
@use './accordion.vars.scss' as accordionVars;

@import '@viasat/beam-tokens/components/Accordion';

$accordionBaseClass: accordionVars.$accordionBaseClass;

$accordionSizes: (
  'sm': (
    'height': tokens.$bm-comp-accordion-size-sm-height,
    'icon': tokens.$bm-comp-accordion-size-sm-icon,
    'header-y': tokens.$bm-comp-accordion-space-sm-header-y,
    'heading': tokens.$bm-comp-accordion-typo-sm-heading,
    'body': tokens.$bm-comp-accordion-typo-sm-body,
    'content-bottom': tokens.$bm-comp-accordion-space-sm-content-bottom,
  ),
  'md': (
    'height': tokens.$bm-comp-accordion-size-md-height,
    'icon': tokens.$bm-comp-accordion-size-md-icon,
    'header-y': tokens.$bm-comp-accordion-space-md-header-y,
    'heading': tokens.$bm-comp-accordion-typo-md-heading,
    'body': tokens.$bm-comp-accordion-typo-md-body,
    'content-bottom': tokens.$bm-comp-accordion-space-md-content-bottom,
  ),
  'lg': (
    'height': tokens.$bm-comp-accordion-size-lg-height,
    'icon': tokens.$bm-comp-accordion-size-lg-icon,
    'header-y': tokens.$bm-comp-accordion-space-lg-header-y,
    'heading': tokens.$bm-comp-accordion-typo-lg-heading,
    'body': tokens.$bm-comp-accordion-typo-lg-body,
    'content-bottom': tokens.$bm-comp-accordion-space-lg-content-bottom,
  ),
);

@mixin accordion-styles($size) {
  .#{$accordionBaseClass}--#{$size} {
    .#{$accordionBaseClass}__container {
      min-height: map.get(map.get($accordionSizes, $size), 'height');
      padding: map.get(map.get($accordionSizes, $size), 'header-y') 0;
    }

    .#{$accordionBaseClass}__chevron {
      height: map.get(map.get($accordionSizes, $size), 'icon');
      min-width: map.get(map.get($accordionSizes, $size), 'icon');
    }

    .#{$accordionBaseClass}__heading {
      font: map.get(map.get($accordionSizes, $size), 'heading');
    }

    .#{$accordionBaseClass}__icon {
      height: map.get(map.get($accordionSizes, $size), 'icon');
    }
  }

  .#{$accordionBaseClass}__panel--#{$size} {
    visibility: hidden;
    font: map.get(map.get($accordionSizes, $size), 'body');
    color: tokens.$bm-comp-accordion-color-body;

    position: relative;

    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows, padding-bottom, 0.2s linear;

    > div {
      overflow: hidden;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: tokens.$bm-comp-accordion-space-content-gap;
      align-self: stretch;

      // due to overflow: hidden - this prevents focus outline clipping
      padding: 0.3rem;
      margin: -0.3rem;
    }

    will-change: grid-template-rows, transform, padding-bottom;
  }

  .#{$accordionBaseClass}__panel--expanded--#{$size} {
    visibility: visible;
    grid-template-rows: 1fr;
    padding-bottom: map.get(map.get($accordionSizes, $size), 'content-bottom');
  }
}

@include accordion-styles('sm');
@include accordion-styles('md');
@include accordion-styles('lg');

.#{$accordionBaseClass} {
  &__container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    gap: tokens.$bm-comp-accordion-space-header-gap;

    &:focus-visible {
      outline: tokens.$bm-sem-border-width-focus solid
        tokens.$bm-sem-color-border-focus;
      border-radius: tokens.$bm-sem-radius-focus-md;
    }
  }

  &__icon {
    flex-shrink: 0;
    display: inline-flex;
    color: tokens.$bm-comp-accordion-color-icon;

    ::slotted([slot='icon']) {
      display: inline-flex;
    }
  }

  &__heading {
    flex-grow: 1;
    color: tokens.$bm-comp-accordion-color-heading;
    display: flex;
    align-items: center;
    gap: tokens.$bm-comp-accordion-space-header-gap;

    ::slotted([slot='heading']) {
      gap: tokens.$bm-comp-accordion-space-header-gap;
    }
  }

  &__chevron {
    transition: transform 0.2s ease;
    color: tokens.$bm-comp-accordion-color-icon;
  }

  &__chevron--rotated {
    transform: rotate(180deg);
  }

  // Divider for React Accordion (only)
  & > div:not(:first-child) > &__container {
    border-top: tokens.$bm-sem-border-width-md solid
      tokens.$bm-comp-accordion-color-divider;
  }

  // Divider for Web-Component Accordion (only)
  :host(:not(:first-of-type)) &__container {
    border-top: tokens.$bm-sem-border-width-md solid
      tokens.$bm-comp-accordion-color-divider;
  }

  // Shadow DOM magic 🤨
  :host(*) &__container {
    box-sizing: border-box;
    &:focus-visible {
      outline: tokens.$bm-sem-border-width-focus solid
        tokens.$bm-sem-color-border-focus;
      border-radius: tokens.$bm-sem-radius-focus-md;
    }
  }

  &--no-box {
    display: contents;
  }
}
