@use 'sass:map';

@use './shared' as *;
@use './design' as *;

$radio: () !default;
$radio: map.merge(
  (
    color-checked-button: #fff,
    bg-color-button: transparent,
    bg-color-checked-button: value('color-primary-base'),
    bg-color-disabled-button: value('fill-color-background'),
    b-color: value('border-color-base'),
    b-color-hover: value('color-primary-base'),
    b-color-checked: value('color-primary-base'),
    b-color-disabled: value('fill-color-disabled'),
    signal-bg-color: transparent,
    signal-bg-color-checked: value('color-primary-base'),
    signal-bg-color-disabled: value('fill-color-disabled'),
    signal-b-color-hover: value('radio-b-color-hover'),
    label-color: inherit,
    label-color-hover-button: value('radio-b-color-hover'),
    label-color-checked: value('color-primary-base'),
    label-color-checked-button: #fff,
    label-color-disabled: value('content-color-disabled'),
    radius: value('radius-base'),
    s-color-focus: value('color-primary-opacity-6'),
    shadow-focus: value('shadow-focus') value('radio-s-color-focus'),
    signal-size: 18px,
    signal-inner-size: 10px,
    button-height: 32px,
    button-v-padding: 0,
    button-h-padding: 10px,
    series-span: 10px
  ),
  $radio
);

.#{$namespace}-radio {
  &-vars {
    @include define-preset-values('radio', $radio);
  }

  @mixin define-radio-style($style-map) {
    @include define-preset-style('radio', $style-map);
  }

  @include basis {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-inline-end: value('radio-series-span');
    vertical-align: middle;
    cursor: pointer;
    user-select: none;
    transition: value('transition-background'), value('transition-border'),
      value('transition-shadow');
  }

  &,
  &--inherit {
    line-height: 1;
  }

  &:last-child {
    margin-inline-end: 0;
  }

  @mixin border-base-style {
    height: value('radio-button-height');
    padding: value('radio-button-v-padding') value('radio-button-h-padding');
    border: value('border-shape') value('radio-b-color');
    border-radius: value('radio-radius');

    &:hover {
      border-color: value('radio-b-color-hover');
    }
  }

  &--border {
    @include border-base-style;
  }

  &--checked#{&}--border {
    border-color: value('radio-b-color-checked');
  }

  &--disabled#{&}--border {
    &,
    &:hover {
      border-color: value('radio-b-color-disabled');
    }
  }

  @mixin button-base-style {
    background-color: value('radio-bg-color-button');

    @include border-base-style;
  }

  &--button {
    @include button-base-style;

    &:focus-within {
      border-color: value('radio-b-color-hover');
      box-shadow: value('radio-shadow-focus');
    }
  }

  &--checked#{&}--button {
    background-color: value('radio-bg-color-checked-button');
    border-color: value('radio-b-color-checked');
  }

  &--disabled#{&}--button {
    &,
    &:hover {
      background-color: value('radio-bg-color-disabled-button');
      border-color: value('radio-b-color-disabled');
    }
  }

  &--loading {
    cursor: auto;
  }

  &__signal {
    @include round-border(value('radio-b-color')) {
      position: relative;
      display: inline-block;
      width: value('radio-signal-size');
      height: value('radio-signal-size');
      background-color: value('radio-signal-bg-color');
      border: value('border-shape') value('radio-b-color');
      border-radius: 50%;
      transition: value('transition-border'), value('transition-shadow');
    }

    &::before {
      opacity: 0%;
    }

    &--active::before {
      opacity: 100%;
    }

    &::after {
      position: absolute;
      top: 50%;
      left: 50%;
      width: value('radio-signal-inner-size');
      height: value('radio-signal-inner-size');
      content: '';
      background-color: value('radio-signal-bg-color-checked');
      border-radius: 50%;
      opacity: 0%;
      transition: value('transition-background'), value('transition-opacity'),
        value('transition-transform');
      transform: translate(-50%, -50%) scale(0);
    }
  }

  &:focus-within &__signal {
    box-shadow: value('radio-shadow-focus');
  }

  &--button &__signal {
    display: none;
  }

  @mixin small-vars {
    @include define-preset-values(
      'radio',
      (
        signal-size: 14px,
        signal-inner-size: 7px,
        button-height: 24px,
        button-h-padding: 8px
      )
    );
  }

  @mixin large-vars {
    @include define-preset-values(
      'radio',
      (
        signal-size: 22px,
        signal-inner-size: 13px,
        button-height: 40px,
        button-h-padding: 14px
      )
    );
  }

  &--small {
    @include small-vars;
  }

  &--large {
    @include large-vars;
  }

  &:hover &__signal {
    &,
    &::before {
      border-color: value('radio-signal-b-color-hover');
    }
  }

  &--checked &__signal {
    &,
    &::before {
      border-color: value('radio-b-color-checked');
    }

    &::after {
      opacity: 100%;
      transform: translate(-50%, -50%) scale(1);
    }
  }

  &__label {
    display: inline-flex;
    align-items: center;
    margin-inline-start: 6px;
    color: value('radio-label-color');
    white-space: nowrap;
    transition: value('transition-color');
  }

  &--button &__label {
    margin-inline-start: 0;
  }

  &--button:hover &__label,
  &--button:focus-within &__label {
    color: value('radio-label-color-hover-button');
  }

  &--checked &__label {
    color: value('radio-label-color-checked');
  }

  &--checked#{&}--button &__label {
    color: value('radio-label-color-checked-button');
  }

  &__loading {
    display: flex;
    align-items: center;
    height: 100%;
    margin-inline-end: 4px;
    pointer-events: none;
    user-select: none;
  }

  $states: success, error, warning;

  @each $state in $states {
    &--#{$state} {
      @include define-radio-style(
        (
          bg-color-checked-button: 'color' $state 'base',
          b-color: 'color' $state 'base',
          b-color-hover: 'color' $state 'base',
          b-color-checked: 'color' $state 'base',
          signal-bg-color-checked: 'color' $state 'base',
          label-color-checked: 'color' $state 'base',
          s-color-focus: 'color' $state 'opacity-6'
        )
      );
    }
  }

  $label: #{&}__label;

  &--disabled {
    cursor: not-allowed;

    &,
    &:hover {
      border-color: value('radio-b-color-disabled');
    }

    &,
    &:hover,
    &:focus-within {
      #{$label} {
        color: value('radio-label-color-disabled');
      }
    }
  }

  &--disabled &__signal,
  &--disabled:hover &__signal {
    &,
    &::before {
      border-color: value('radio-b-color-disabled');
    }

    &::after {
      background-color: value('radio-signal-bg-color-disabled');
    }
  }

  &__input {
    width: 0;
    height: 0;
    margin: 0;
    pointer-events: none;
    opacity: 0%;
  }

  @at-root {
    &-group {
      @include basis {
        display: inline-flex;
        align-items: center;
        justify-content: flex-start;
      }

      &--vertical {
        flex-direction: column;
        align-items: flex-start;
        justify-content: center;
      }
    }

    &-group--vertical & {
      margin-inline-end: 0;
      margin-bottom: 6px;

      &:last-child {
        margin-bottom: 0;
      }
    }

    $radius: value('radius-base');
    $bw: value('border-width');
    $rbw: calc(value('border-width') * -1);

    &-group--button-group & {
      position: relative;
      z-index: 0;
      height: value('radio-button-height');
      padding: value('radio-button-v-padding') value('radio-button-h-padding');
      margin: 0;
      border: value('border-shape') value('radio-b-color');
      border-inline-start-width: 0;
      border-radius: 0;

      &::after {
        position: absolute;
        inset-inline-start: $rbw;
        top: 0;
        bottom: 0;
        display: block;
        width: $bw;
        content: '';
        background-color: transparent;
        transition: value('transition-background');
      }

      &:hover {
        border-color: value('radio-b-color-checked');
        box-shadow: $rbw 0 0 0 value('radio-b-color-checked');

        @include rtl {
          box-shadow: $bw 0 0 0 value('radio-b-color-checked');
        }
      }

      &:hover #{$label},
      &:focus-within #{$label} {
        color: value('radio-label-color-hover-button');
      }

      &:first-child {
        @include logical-radius($radius 0 0 $radius);

        border-inline-start-width: $bw;
        box-shadow: none;

        @include rtl {
          box-shadow: none;
        }

        &::after {
          content: none;
        }
      }

      &:last-child {
        @include logical-radius(0 $radius $radius 0);
      }

      &--checked {
        z-index: 1;
        border-color: value('radio-b-color-checked');
        box-shadow: $rbw 0 0 0 value('radio-b-color-checked');

        @include rtl {
          box-shadow: $bw 0 0 0 value('radio-b-color-checked');
        }
      }

      &:focus-within {
        border-color: value('radio-b-color-hover');
        box-shadow:
          $rbw 0 0 0 value('radio-b-color-hover'),
          value('radio-shadow-focus');

        @include rtl {
          box-shadow:
            $bw 0 0 0 value('radio-b-color-hover'),
            value('radio-shadow-focus');
        }

        &::after {
          inset-inline-start: -3px;
          top: -3px;
          bottom: -3px;
          background-color: value('radio-s-color-focus');
          opacity: 50%;
        }
      }

      &:focus-within:first-child {
        box-shadow: value('radio-shadow-focus');

        @include rtl {
          box-shadow: value('radio-shadow-focus');
        }
      }

      &__signal {
        display: none;
      }

      &__label {
        margin-inline-start: 0;
      }
    }

    &-group--vertical#{&}-group--button-group & {
      border-inline-start-width: $bw;
      border-top-width: 0;

      &::after {
        inset: $rbw 0 auto;
        width: auto;
        height: $bw;
      }

      &:hover {
        box-shadow: 0 $rbw 0 0 value('radio-b-color-checked');

        @include rtl {
          box-shadow: 0 $bw 0 0 value('radio-b-color-checked');
        }
      }

      &:first-child {
        @include logical-radius($radius $radius 0 0);

        border-top-width: $bw;
        box-shadow: none;

        @include rtl {
          box-shadow: none;
        }

        &::after {
          content: none;
        }
      }

      &:last-child {
        @include logical-radius(0 0 $radius $radius);
      }

      &--checked {
        box-shadow: 0 $rbw 0 0 value('radio-b-color-checked');

        @include rtl {
          box-shadow: 0 $bw 0 0 value('radio-b-color-checked');
        }
      }

      &:focus-within {
        box-shadow:
          0 $rbw 0 0 value('radio-b-color-hover'),
          value('radio-shadow-focus');

        @include rtl {
          box-shadow:
            0 $bw 0 0 value('radio-b-color-hover'),
            value('radio-shadow-focus');
        }

        &::after {
          inset-inline: -3px;
          top: -3px;
          bottom: auto;
        }
      }

      &:focus-within:first-child {
        box-shadow: value('radio-shadow-focus');

        @include rtl {
          box-shadow: value('radio-shadow-focus');
        }
      }
    }

    &-group--small & {
      @include small-vars;
    }

    &-group--large & {
      @include large-vars;
    }

    &-group--button-group#{&}-group--disabled &,
    &-group--button-group &--disabled {
      background-color: value('radio-bg-color-disabled-button');
      border-color: value('radio-b-color') !important;
      box-shadow: none !important;

      &,
      &:hover,
      &:focus-within {
        #{$label} {
          color: value('radio-label-color-disabled');
        }
      }
    }

    &-group--button-group &--disabled#{&}--checked,
    &-group--button-group#{&}-group--disabled &--checked {
      background-color: value('radio-bg-color-disabled-button');

      #{$label} {
        color: value('radio-label-color-disabled');
      }
    }
  }
}
