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

const props = defineProps<{
  isRecording: boolean
  voiceMode: 'web' | 'whisper'
  whisperStatus: 'offline' | 'loading' | 'ready'
  disabled?: boolean
}>()

const emit = defineEmits<{
  start: []
  stop: []
}>()

// ── Interaction state machine ──
// idle       → pointerdown → wait 250ms
//              if pointerup < 250ms  → "click" → locked (recording until next press+release)
//              if 250ms passes       → "hold"  → ptt (recording until release + 500ms trail)
// locked     → pointerdown → stopping
// stopping   → pointerup   → stop recording → idle
// ptt        → pointerup   → wait 500ms trail → stop recording → idle

type Mode = 'idle' | 'locked' | 'ptt' | 'stopping'
const mode = ref<Mode>('idle')

const HOLD_THRESHOLD = 250
const TRAIL_BUFFER = 500

let holdTimer: number | null = null
let trailTimer: number | null = null

function clearTimers() {
  if (holdTimer) { clearTimeout(holdTimer); holdTimer = null }
  if (trailTimer) { clearTimeout(trailTimer); trailTimer = null }
}

function onPointerDown(e: PointerEvent) {
  if (props.disabled) return
  e.preventDefault()
  // Capture pointer so we get pointerup even if cursor leaves button
  ;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)

  if (mode.value === 'idle') {
    // Start hold detection
    holdTimer = window.setTimeout(() => {
      holdTimer = null
      // Still holding after 250ms → PTT mode
      mode.value = 'ptt'
      emit('start')
    }, HOLD_THRESHOLD)
  } else if (mode.value === 'locked') {
    // Second press while locked → prepare to stop on release
    mode.value = 'stopping'
  }
}

function onPointerUp(e: PointerEvent) {
  if (props.disabled) return
  e.preventDefault()

  if (mode.value === 'idle' && holdTimer) {
    // Quick click (< 250ms) → lock mode
    clearTimers()
    mode.value = 'locked'
    emit('start')
  } else if (mode.value === 'ptt') {
    // Release from PTT → 500ms trailing buffer then stop
    clearTimers()
    trailTimer = window.setTimeout(() => {
      trailTimer = null
      mode.value = 'idle'
      emit('stop')
    }, TRAIL_BUFFER)
  } else if (mode.value === 'stopping') {
    // Release from second press → stop immediately
    clearTimers()
    mode.value = 'idle'
    emit('stop')
  }
}

onBeforeUnmount(() => {
  clearTimers()
})
</script>

<template>
  <button
    class="mic-btn"
    :class="{ recording: isRecording, ptt: mode === 'ptt', disabled }"
    :disabled="disabled"
    @pointerdown="onPointerDown"
    @pointerup="onPointerUp"
    :title="isRecording ? (mode === 'ptt' ? 'Release to stop' : 'Click to stop') : 'Click or hold to record'"
  >
    <!-- Mic icon -->
    <svg v-if="!isRecording" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
      <path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
      <line x1="12" y1="19" x2="12" y2="23"/>
      <line x1="8" y1="23" x2="16" y2="23"/>
    </svg>
    <!-- Stop icon (square) when recording -->
    <svg v-else width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
      <rect x="4" y="4" width="16" height="16" rx="2"/>
    </svg>
    <!-- Mode badge -->
    <span class="mode-badge" :class="voiceMode">
      {{ voiceMode === 'whisper' ? 'GPU' : 'WEB' }}
    </span>
  </button>
</template>

<style scoped>
.mic-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  background: var(--bg-hover, rgba(255,255,255,0.06));
  border: 1px solid var(--border-color, rgba(255,255,255,0.08));
  border-radius: 6px;
  color: var(--text-muted, #888);
  cursor: pointer;
  flex-shrink: 0;
  transition: all 0.15s;
  touch-action: none;
  user-select: none;
}

.mic-btn:hover:not(:disabled) {
  background: var(--bg-hover, rgba(255,255,255,0.1));
  color: var(--text-primary, #ccc);
  border-color: var(--text-muted, rgba(255,255,255,0.15));
}

.mic-btn.recording {
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
  border-color: rgba(239, 68, 68, 0.5);
  color: white;
  animation: rec-pulse 1.5s ease-in-out infinite;
}

.mic-btn.recording.ptt {
  background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
  border-color: rgba(249, 115, 22, 0.5);
  animation: rec-pulse-ptt 0.8s ease-in-out infinite;
}

.mic-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.mode-badge {
  position: absolute;
  bottom: -4px;
  right: -4px;
  font-size: 7px;
  font-weight: 700;
  font-family: 'Courier New', monospace;
  padding: 1px 3px;
  border-radius: 3px;
  line-height: 1;
  letter-spacing: 0.3px;
  pointer-events: none;
}

.mode-badge.whisper {
  background: rgba(16, 185, 129, 0.9);
  color: white;
}

.mode-badge.web {
  background: rgba(59, 130, 246, 0.9);
  color: white;
}

@keyframes rec-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
  50% { box-shadow: 0 0 0 4px rgba(239, 68, 68, 0); }
}

@keyframes rec-pulse-ptt {
  0%, 100% { box-shadow: 0 0 0 0 rgba(249, 115, 22, 0.5); transform: scale(1); }
  50% { box-shadow: 0 0 0 5px rgba(249, 115, 22, 0); transform: scale(1.08); }
}
</style>
