<template>
  <div class="cpTextarea">
    <base-input-label
      v-if="label"
      v-bind-once="{ for: inputIdentifier }"
      class="cpTextarea__label"
      :is-invalid="isInvalid"
      :required="required"
    >
      {{ capitalizedLabel }}
    </base-input-label>
    <textarea
      v-model="textareaModel"
      v-bind-once="{ id: inputIdentifier }"
      class="cpTextarea__input"
      :class="{ 'cpTextarea__input--isInvalid': isInvalid }"
      :disabled="disabled"
      :placeholder="placeholder"
      :required="required"
      :style="`min-height: ${height}px`"
    />
    <cp-transition-expand>
      <p v-if="displayErrorMessage" class="cpTextarea__error">
        {{ errorMessage }}
      </p>
    </cp-transition-expand>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, useId } from 'vue'

import BaseInputLabel from '@/components/BaseInputLabel.vue'
import CpTransitionExpand from '@/components/CpTransitionExpand.vue'

import { capitalizeFirstLetter } from '@/helpers'

interface Emits {
  (e: 'update:modelValue', value: string): void
}

interface Props {
  disabled?: boolean
  errorMessage?: string
  height?: number
  inputId?: string
  isInvalid?: boolean
  label?: string
  modelValue?: string
  placeholder?: string
  required?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  label: '',
  placeholder: '',
  required: false,
  inputId: '',
  disabled: false,
  isInvalid: false,
  errorMessage: '',
  height: 200,
})

const emit = defineEmits<Emits>()

const textareaModel = defineModel<string>({
  type: String,
  default: '',
  required: false,
  set(newValue) {
    handleChange(newValue)
    return newValue
  },
})

const inputIdentifier = ref(props.inputId || useId())

const capitalizedLabel = computed(() => capitalizeFirstLetter(props.label))

const displayErrorMessage = computed(() => props.isInvalid && props.errorMessage.length)

const handleChange = (newValue: string) => emit('update:modelValue', newValue)
</script>

<style lang="scss">
.cpTextarea {
  position: relative;

  &__input {
    width: 100%;
    max-width: 100%;
    height: 100%;
    padding: var(--cp-spacing-xl);
    border: none;
    border-radius: var(--cp-radius-md-lg);
    appearance: none;
    box-shadow:
      var(--cp-shadows-3xs),
      0 0 0 var(--cp-dimensions-0_25) var(--cp-border-soft);
    color: var(--cp-text-primary);
    font-size: var(--cp-text-size-md);
    outline: none;

    &:hover {
      box-shadow:
        var(--cp-shadows-3xs),
        0 0 0 var(--cp-dimensions-0_25) var(--cp-border-soft-hover);
    }

    &:focus {
      background-color: var(--cp-background-primary);
      outline: var(--cp-dimensions-0_5) solid var(--cp-focus);
    }

    &:disabled {
      background: var(--cp-background-disabled);
      box-shadow: 0 0 0 var(--cp-dimensions-0_25) var(--cp-border-disabled);
      color: var(--cp-text-disabled);
      cursor: not-allowed;

      &::placeholder {
        color: var(--cp-text-disabled);
      }
    }

    &::placeholder {
      color: var(--cp-text-placeholder);
    }

    &--isInvalid {
      box-shadow:
        var(--cp-shadows-3xs),
        0 0 0 var(--cp-dimensions-0_25) var(--cp-border-error-solid);

      &:hover,
      &:focus {
        box-shadow:
          var(--cp-shadows-3xs),
          0 0 0 var(--cp-dimensions-0_25) var(--cp-border-error-solid);
      }

      &:focus {
        outline: var(--cp-dimensions-0_5) solid var(--cp-border-error-solid);
      }
    }
  }

  &__error {
    color: var(--cp-text-error-primary);
    font-size: var(--cp-text-size-sm);
    line-height: var(--cp-line-height-md);
  }
}
</style>
