<script setup lang="ts">
/**
 * Input — text field with label, hint/error, leading icon and affixes.
 * Reach for `mono` on any technical value (ports, tokens, IDs).
 * v-model binds to the inner <input> value via defineModel<string>().
 */
import Icon from '@/components/ds/core/Icon.vue'

const props = withDefaults(
  defineProps<{
    label?: string
    hint?: string
    error?: string
    icon?: string
    prefix?: string
    suffix?: string
    size?: 'md' | 'sm'
    mono?: boolean
    required?: boolean
    id?: string
    placeholder?: string
    disabled?: boolean
    type?: string
  }>(),
  { size: 'md', mono: false, required: false, disabled: false, type: 'text' },
)

const model = defineModel<string>()

const invalid = () => !!props.error
</script>

<template>
  <label
    class="cc-field"
    :for="id"
  >
    <span v-if="label" class="cc-field__label">
      {{ label }}<span v-if="required" class="req">*</span>
    </span>
    <span
      :class="[
        'cc-input',
        size === 'sm' && 'cc-input--sm',
        mono && 'cc-input--mono',
        invalid() && 'cc-input--invalid',
      ]"
    >
      <Icon v-if="icon" :name="icon" :size="15" />
      <span v-if="prefix" class="cc-input__affix">{{ prefix }}</span>
      <input
        :id="id"
        :type="type"
        :placeholder="placeholder"
        :disabled="disabled"
        :value="model"
        @input="model = ($event.target as HTMLInputElement).value"
      />
      <span v-if="suffix" class="cc-input__affix">{{ suffix }}</span>
    </span>
    <span
      v-if="hint || error"
      :class="['cc-field__hint', invalid() && 'cc-field__hint--error']"
    >{{ error ?? hint }}</span>
  </label>
</template>

<style>
.cc-field { display:flex; flex-direction:column; gap:6px; }
.cc-field__label { font-size:var(--text-xs); font-weight:600; color:var(--text-secondary); }
.cc-field__label .req { color:var(--accent-text); margin-left:2px; }
.cc-input {
  display:flex; align-items:center; gap:8px; height:var(--control-h-md); padding:0 11px;
  background:var(--surface-inset); border-radius:var(--radius-md); box-shadow:var(--ring-default);
  transition:var(--transition-colors); color:var(--text-tertiary);
}
.cc-input:focus-within { box-shadow: inset 0 0 0 1px var(--accent), var(--glow-accent-sm); }
.cc-input--sm { height:var(--control-h-sm); padding:0 9px; }
.cc-input--invalid { box-shadow: inset 0 0 0 1px var(--status-offline-border); }
.cc-input--invalid:focus-within { box-shadow: inset 0 0 0 1px var(--danger); }
.cc-input input {
  flex:1; min-width:0; background:transparent; border:0; outline:0; padding:0; margin:0;
  font-family:var(--font-sans); font-size:var(--text-sm); color:var(--text-primary);
}
.cc-input input::placeholder { color:var(--text-muted); }
.cc-input--mono input { font-family:var(--font-mono); }
.cc-input__affix { font-family:var(--font-mono); font-size:var(--text-xs); color:var(--text-muted); white-space:nowrap; }
.cc-field__hint { font-size:var(--text-xs); color:var(--text-tertiary); }
.cc-field__hint--error { color:var(--danger); }
</style>
