@use 'sass:map';
@use '@mezzanine-ui/system/palette' as palette;
@use '@mezzanine-ui/system/spacing' as spacing;
@use '@mezzanine-ui/system/radius' as radius;
@use '@mezzanine-ui/system/effect' as effect;
@use '@mezzanine-ui/system/transition' as transition;
@use './selection-card' as *;

$input-size: spacing.primitive-variable(12);
$input-offset: spacing.primitive-variable(12);

// Horizontal direction configurations
$horizontal-configs: (
  no-image: (
    min-width: spacing.semantic-variable(size, container, snug),
  ),
  with-image: (
    min-width: spacing.semantic-variable(size, container, tight),
  ),
);

// Vertical direction configurations
$vertical-configs: (
  no-image: (
    min-width: spacing.semantic-variable(size, container, snug),
  ),
  with-image: (
    min-width: none,
  ),
);

// State configurations
$states: (
  enable: (
    text-color: palette.semantic-variable(text, neutral-strong),
    background-color: palette.semantic-variable(background, base),
    border-color: palette.semantic-variable(border, neutral-faint),
  ),
  hover: (
    text-color: palette.semantic-variable(text, neutral-strong),
    background-color: palette.semantic-variable(background, base),
    border-color: palette.semantic-variable(border, neutral-faint),
  ),
  active: (
    text-color: palette.semantic-variable(text, neutral-solid),
    background-color: palette.semantic-variable(background, neutral-faint),
    border-color: palette.semantic-variable(border, neutral-faint),
  ),
  focus: (
    text-color: palette.semantic-variable(text, neutral-strong),
    background-color: palette.semantic-variable(background, base),
    border-color: palette.semantic-variable(border, neutral-faint),
    focus-color: effect.variable(focus, primary),
  ),
  selected: (
    text-color: palette.semantic-variable(text, neutral-strong),
    background-color: palette.semantic-variable(background, base),
    border-color: palette.semantic-variable(border, brand),
  ),
  disabled: (
    text-color: palette.semantic-variable(text, neutral-light),
    background-color: palette.semantic-variable(background, neutral-subtle),
    border-color: palette.semantic-variable(border, neutral-faint),
  ),
);

@function _get-state-config($state) {
  @return map.get($states, $state);
}

@function _get-color($state, $property) {
  $state-config: _get-state-config($state);

  @if $state-config {
    @return map.get($state-config, $property);
  }

  @return null;
}

@mixin _apply-state($state) {
  $text-color: _get-color($state, text-color);
  $background-color: _get-color($state, background-color);
  $border-color: _get-color($state, border-color);
  $focus-color: _get-color($state, focus-color);

  @if $text-color {
    color: $text-color;
  }

  @if $background-color {
    background-color: $background-color;
  }

  @if $border-color {
    border-color: $border-color;
  }

  @if $focus-color {
    --#{$prefix}-focus-color: #{$focus-color};
  }
}

@function _get-horizontal-config($type, $property) {
  $config: map.get($horizontal-configs, $type);

  @if $config {
    @return map.get($config, $property);
  }

  @return null;
}

@mixin _apply-horizontal-config($type) {
  $min-width: _get-horizontal-config($type, min-width);

  @if $min-width {
    min-width: $min-width;
  }
}

@function _get-vertical-config($type, $property) {
  $config: map.get($vertical-configs, $type);

  @if $config {
    @return map.get($config, $property);
  }

  @return null;
}

@mixin _apply-vertical-config($type) {
  $min-width: _get-vertical-config($type, min-width);

  @if $min-width and $min-width != none {
    min-width: $min-width;
  }
}

.#{$prefix} {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid palette.semantic-variable(border, neutral-faint);
  border-radius: radius.variable(roomy);
  background-color: palette.semantic-variable("background", base);
  cursor: pointer;
  user-select: none;
  width: fit-content;
  max-width: 100%;
  height: fit-content;
  padding-inline: spacing.semantic-variable(padding, horizontal, base-fixed);
  padding-block: spacing.semantic-variable(padding, vertical, base);
  gap: spacing.semantic-variable(gap, base);
  transition:
    transition.standard(color),
    transition.standard(background-color),
    transition.standard(border-color),
    transition.standard(box-shadow);

  @include _apply-state(enable);

  &:hover:not(.#{$prefix}--disabled):not(.#{$prefix}--selected) {
    @include _apply-state(hover);

    box-shadow: effect.variable(shadow, floating);
  }

  &:active:not(.#{$prefix}--disabled):not(.#{$prefix}--selected) {
    @include _apply-state(active);
  }

  &:focus {
    outline: none;
  }

  &:focus-visible,
  &:has(input:focus-visible) {
    outline: none;
    @include _apply-state(focus);

    box-shadow: effect.variable(focus, primary);
  }

  // Selected state (when input is checked)
  &:has(input:checked):not(.#{$prefix}--disabled),
  &--selected:not(.#{$prefix}--disabled) {
    cursor: default;
    @include _apply-state(selected);

    // Selected + hover
    &:hover {
      @include _apply-state(selected);

      box-shadow: effect.variable(shadow, floating);
    }

    // Selected + focus
    &:focus {
      outline: none;
    }

    &:focus-visible,
    &:has(input:focus-visible) {
      outline: none;
      @include _apply-state(selected);

      box-shadow: effect.variable(focus, primary);
    }
  }

  &--disabled {
    cursor: not-allowed;
    @include _apply-state(disabled);
  }

  &--readonly:not(.#{$prefix}--disabled) {
    cursor: auto;
  }

  // Selected + disabled (when input is checked and disabled)
  &:has(input:checked).#{$prefix}--disabled,
  &--selected.#{$prefix}--disabled {
    @include _apply-state(disabled);
  }

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

  &__content {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    flex-direction: column;
    flex: 1 1 auto;
    gap: spacing.semantic-variable(gap, tiny);
    min-inline-size: 0;
  }

  &__text {
    overflow: hidden;
    color: palette.semantic-variable(text, neutral-solid);
    font-feature-settings: 'liga' off, 'clig' off;
    min-inline-size: 0;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &--disabled &__text {
    color: palette.semantic-variable(text, neutral-light);
  }

  &__supporting-text {
    overflow: hidden;
    color: palette.semantic-variable(text, neutral);
    font-feature-settings: 'liga' off, 'clig' off;
    min-inline-size: 0;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &--disabled &__supporting-text {
    color: palette.semantic-variable(text, neutral-light);
  }

  &__icon {
    width: spacing.semantic-variable(size, element, relaxed);
  }

  &--disabled &__icon {
    color: palette.semantic-variable(icon, neutral-light);
  }

  &__selection-image {
    border-radius: radius.variable(base);
  }

  &--disabled &__selection-image {
    background-color: palette.semantic-variable(surface, subtle);
  }

  &--horizontal &__selection-image {
    width: spacing.semantic-variable(size, element, extra-wide);
    height: spacing.semantic-variable(size, element, extra-wide);
  }

  &__container {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 auto;
    gap: spacing.semantic-variable(gap, base);
    min-width: 0;
  }

  &--horizontal:not(:has(&__selection-image)) {
    @include _apply-horizontal-config(no-image);
  }

  &--horizontal:has(&__selection-image) {
    @include _apply-horizontal-config(with-image);
  }

  &--vertical {
    align-items: flex-start;
  }

  &--vertical:not(:has(&__selection-image)) {
    @include _apply-vertical-config(no-image);
  }

  &--vertical:has(&__selection-image) {
    @include _apply-vertical-config(with-image);
  }

  &--vertical &__container {
    flex-direction: column;
    align-items: flex-start;
  }

  &--vertical &__selection-image {
    width: 100%;
    height: 100%;
  }

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

  &__input {
    appearance: none;
    margin: 0;
    margin-inline: spacing.semantic-variable(padding, horizontal, micro);
    margin-block: spacing.semantic-variable(padding, vertical, micro);
    width: $input-size;
    height: $input-size;
    border: 1px solid;
    border-color: palette.semantic-variable(border, neutral);

    &[type="radio"] {
      position: relative;
      border-radius: 50%;

      &::before {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: spacing.primitive-variable(6);
        height: spacing.primitive-variable(6);
        border-radius: 50%;
        background-color: transparent;
        transition: transition.standard(background-color);
      }

      &:checked {
        border-color: palette.semantic-variable(border, brand);

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

      &:disabled {
        border-color: palette.semantic-variable("background", neutral);

        &:checked::before {
          background-color: palette.semantic-variable("background", neutral);
        }
      }
    }

    &[type="checkbox"] {
      position: relative;
      border-radius: radius.variable(tiny);

      &::after {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -65%) rotate(-45deg) scaleX(-1);
        width: spacing.primitive-variable(6);
        height: spacing.primitive-variable(3);
        border: spacing.primitive-variable(2) solid;
        border-top: none;
        border-left: none;
        border-color: palette.semantic-variable(icon, fixed-light);
        opacity: 0;
        transition: transition.standard(opacity);
      }

      &:checked {
        background-color: palette.semantic-variable("background", brand);
        border-color: palette.semantic-variable(border, brand);

        &::after {
          opacity: 1;
        }
      }

      &:disabled {
        background-color: palette.semantic-variable("background", neutral-subtle);
        border-color: palette.semantic-variable(border, neutral-light);

        &::after {
          border-color: palette.semantic-variable(icon, neutral-light);
        }
      }
    }

    &:focus,
    &:focus-visible,
    &:focus-within {
      outline: none;
    }
  }

  &--vertical:has(&__selection-image) &__input {
    position: absolute;
    right: $input-offset;
    top: $input-offset;
  }

  &-group {
    display: flex;
    flex-wrap: wrap;
    width: fit-content;
    max-width: 100%;
    gap: spacing.semantic-variable(gap, calm);
  }

}
