@use 'sass:map';

@use './shared' as *;
@use './design' as *;

$input: () !default;
$input: map.merge(
  (
    bg-color: value('fill-color-base'),
    bg-color-disabled: value('fill-color-humble'),
    b-color: value('border-color-base'),
    b-color-hover: value('color-primary-light-1'),
    b-color-focus: value('input-b-color-hover'),
    s-color-focus: value('color-primary-opacity-6'),
    placeholder-color: value('content-color-placeholder'),
    control-color: value('content-color-base'),
    control-color-disabled: value('content-color-disabled'),
    icon-color: value('content-color-secondary'),
    icon-color-hover: value('color-primary-base'),
    icon-color-disabled: value('input-control-color-disabled'),
    before-bg-color: value('fill-color-background'),
    after-bg-color: value('fill-color-background'),
    line-height: value('line-height-base'),
    border: value('border-shape') value('input-b-color'),
    radius: value('radius-base'),
    count-color: value('content-color-secondary'),
    count-color-disabled: value('input-control-color-disabled'),
    count-font-size: value('font-size-secondary'),
    count-line-height: value('line-height-secondary'),
    height: 32px,
    v-padding: 4px,
    h-padding: 8px,
    padding: value('input-v-padding') value('input-h-padding'),
    prefix-width: 32px,
    suffix-width: 32px
  ),
  $input
);

@mixin define-input-style($style-map) {
  @include define-preset-style('input', $style-map);
}

@mixin handler($handler: &) {
  @at-root #{$handler} {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: 100%;
    height: value('input-height');
    padding: value('input-v-padding') value('input-h-padding');
    cursor: text;
    background-color: value('input-bg-color');
    border: value('border-shape') value('input-b-color');
    border-radius: value('input-radius');
    outline: 0;
    transition:
      value('transition-background'), value('transition-border'), value('transition-shadow');

    &:hover {
      border-color: value('input-b-color-hover');
    }

    &:focus,
    &:focus-within,
    &--focused {
      z-index: 2;
      border-color: value('input-b-color-focus');
      box-shadow: value('shadow-focus') value('input-s-color-focus');
    }

    &--small {
      @include define-preset-values(
        'input',
        (
          height: 24px,
          v-padding: 1px
        )
      );
    }

    &--large {
      @include define-preset-values(
        'input',
        (
          height: 40px,
          v-padding: 7px
        )
      );
    }

    $states: success, error, warning;

    @each $state in $states {
      // 提升 state 样式的级别，以防止引入的先后顺序导致样式丢失
      &#{&}--#{$state} {
        @include define-input-style(
          (
            b-color: 'color' $state 'light-1',
            b-color-hover: 'color' $state 'light-1',
            s-color-focus: 'color' $state 'opacity-6'
          )
        );
      }
    }

    &--readonly {
      cursor: auto;
    }

    &--transparent {
      background-color: transparent;

      &,
      &:hover,
      &:focus,
      &:focus-within,
      &--focused {
        border-color: transparent;
        box-shadow: unset;
      }
    }

    &--disabled {
      cursor: not-allowed;
      background-color: value('input-bg-color-disabled');

      &,
      &:hover,
      &:focus,
      &:focus-within {
        border-color: value('border-color-base');
        box-shadow: none;
      }

      %disabled-item {
        color: value('input-control-color-disabled');
        pointer-events: none;
        cursor: not-allowed;
      }
    }

    &--disabled#{&}--focused {
      border-color: value('border-color-base');
      box-shadow: none;
    }
  }

  &__control {
    flex: 1 0 0;
    min-width: 0;
    height: 100%;
    padding: 0;
    font-size: inherit;
    line-height: value('input-line-height');
    color: value('input-control-color');
    background-color: transparent;
    border: 0;
    border-radius: value('input-radius');
    outline: 0;
    transition: value('transition-color');

    &:disabled {
      cursor: not-allowed;
    }

    &::placeholder {
      color: value('input-placeholder-color');
    }

    /* stylelint-disable no-duplicate-selectors */
    &::-ms-clear,
    &::-ms-clear,
    &::-ms-reveal,
    &::-ms-reveal {
      display: none;
    }
    /* stylelint-enable no-duplicate-selectors */

    @extend %disabled-item;
  }

  #{$handler}--readonly &__control {
    cursor: auto;
  }

  &__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: value('input-icon-color');
    user-select: none;

    &--placeholder {
      min-width: 14px;
      min-height: 1px;
      margin-inline-start: 4px;
      visibility: hidden;
      opacity: 0%;
    }

    @extend %disabled-item;
  }

  &__prefix {
    margin-inline-end: 4px;
  }

  &__suffix {
    margin-inline-start: 4px;
    transition: value('transition-opacity');
  }

  &__clear {
    @include clean-button;
  }

  &__clear,
  &__loading {
    position: absolute;
    inset-inline-end: value('input-h-padding');
    min-width: 14px;
    margin-inline-start: 4px;
    cursor: pointer;
  }

  &__loading {
    pointer-events: none;
  }
}

.#{$namespace}-input {
  @at-root &-vars {
    @include define-preset-values('input', $input);
  }

  $self: &;
  $wrapper: #{&}-wrapper;
  $radius: value('input-radius');

  &-wrapper {
    @include basis {
      position: relative;
      display: inline-flex;
      align-items: center;
      width: 100%;
      min-width: 0;
      background-color: value('input-bg-color');
      border-radius: value('input-radius');
    }
  }

  @include basis;
  @include handler;

  &-wrapper & {
    flex: 1 0 0;
    width: auto;
    min-width: 0;
    background-color: transparent;
    border-radius: 0;
  }

  &-wrapper--before-only & {
    @include logical-radius(0 $radius $radius 0);
  }

  &-wrapper--after-only & {
    @include logical-radius($radius 0 0 $radius);
  }

  &--before {
    z-index: 1;
    border-inline-start-color: transparent;
  }

  &--after {
    z-index: 1;
    border-inline-end-color: transparent;
  }

  &__suffix-wrapper {
    position: relative;
    display: flex;
    align-items: center;
  }

  &__clear,
  &__loading {
    inset-inline-end: 0;
  }

  &__password {
    margin-inline-start: 4px;
    cursor: pointer;
  }

  &__count {
    margin: 0 4px;
    font-size: value('input-count-font-size');
    line-height: value('input-count-line-height');
    color: value('input-count-color');
    pointer-events: none;
    user-select: none;
    transition: value('transition-color');
  }

  &--disabled &__count {
    color: value('input-count-color-disabled');
  }

  &__before,
  &__after {
    position: relative;
    display: flex;
    align-items: center;
    height: calc(value('input-height'));
    padding: 0 value('input-h-padding');
    border: value('input-border');

    &--action {
      padding: 0;
      border: 0;
    }
  }

  @mixin inner-input($inner-radius) {
    & > #{$wrapper},
    & > .#{$namespace}-number-input {
      width: calc(100% + 2 * value('input-h-padding'));
      height: 100%;

      @include logical-radius($inner-radius);
    }
  }

  @mixin inner-select($inner-radius) {
    $selects: cascader color-picker date-picker select time-picker;

    @each $select in $selects {
      & > .#{$namespace}-#{$select} {
        width: calc(100% + 2 * value('input-h-padding'));
        height: 100%;

        & .#{$namespace}-#{$select}__selector {
          min-width: 60px;
          height: 100%;
          background-color: transparent;
          box-shadow: unset;

          @include logical-radius($inner-radius);
        }
      }
    }
  }

  @mixin inner-button($inner-radius) {
    & > .#{$namespace}-button {
      width: calc(100% + 2 * value('input-h-padding'));
      height: 100%;

      @include logical-radius($inner-radius);

      &--icon-only {
        width: calc(value('button-height') + 2 * value('input-h-padding'));
      }
    }
  }

  $before-radius: $radius 0 0 $radius;
  $after-radius: 0 $radius $radius 0;

  &__before {
    $bg-color: value('input-before-bg-color');

    background-color: $bg-color;
    border-inline-end: 0;

    @include logical-radius($radius 0 0 $radius);

    &--action {
      margin-inline-end: -1px;
      background-color: transparent;

      @include inner-button($before-radius);
      @include inner-input($before-radius);
      @include inner-select($before-radius);
    }
  }

  &__after {
    $bg-color: value('input-after-bg-color');

    background-color: $bg-color;
    border-inline-start: 0;

    @include logical-radius(0 $radius $radius 0);

    &--action {
      margin-inline-start: -1px;
      background-color: transparent;

      @include inner-button($after-radius);
      @include inner-input($after-radius);
      @include inner-select($after-radius);
    }
  }

  &--transparent &__before,
  &--transparent &__after {
    background-color: transparent;
  }
}
