import React, { useState, useRef, useEffect } from 'react'
import './InputArea.css'
import sendIcon from '../assets/send-icon.svg'

const MAX_IMAGE_DIMENSION = 1600
const JPEG_QUALITY = 0.82

const fileToDataUrl = (file) => new Promise((resolve, reject) => {
  const reader = new FileReader()
  reader.onload = () => resolve(String(reader.result || ''))
  reader.onerror = () => reject(new Error('Impossibile leggere il file selezionato'))
  reader.readAsDataURL(file)
})

const loadImageElement = (file) => new Promise((resolve, reject) => {
  const image = new Image()
  const objectUrl = URL.createObjectURL(file)

  image.onload = () => {
    URL.revokeObjectURL(objectUrl)
    resolve(image)
  }

  image.onerror = () => {
    URL.revokeObjectURL(objectUrl)
    reject(new Error('Impossibile aprire l\'immagine selezionata'))
  }

  image.src = objectUrl
})

const resizeImageFile = async (file) => {
  if (!file.type.startsWith('image/')) {
    return fileToDataUrl(file)
  }

  try {
    const image = await loadImageElement(file)
    const longestSide = Math.max(image.width, image.height)

    if (longestSide <= MAX_IMAGE_DIMENSION && file.size <= 1_500_000) {
      return fileToDataUrl(file)
    }

    const scale = MAX_IMAGE_DIMENSION / longestSide
    const width = Math.max(1, Math.round(image.width * scale))
    const height = Math.max(1, Math.round(image.height * scale))
    const canvas = document.createElement('canvas')
    canvas.width = width
    canvas.height = height

    const context = canvas.getContext('2d')
    if (!context) {
      return fileToDataUrl(file)
    }

    context.drawImage(image, 0, 0, width, height)
    return canvas.toDataURL('image/jpeg', JPEG_QUALITY)
  } catch (error) {
    console.error('Errore compressione immagine:', error)
    return fileToDataUrl(file)
  }
}

function InputArea({ onSendMessage, isLoading, allowPhotoUpload = false }) {
  const [input, setInput] = useState('')
  const [isListening, setIsListening] = useState(false)
  const [selectedPhotos, setSelectedPhotos] = useState([])
  const [micError, setMicError] = useState('')
  const recognitionRef = useRef(null)
  const shouldKeepListeningRef = useRef(false)
  const baseInputRef = useRef('')
  const finalTranscriptRef = useRef('')

  useEffect(() => () => {
    shouldKeepListeningRef.current = false
    if (recognitionRef.current) {
      recognitionRef.current.onstart = null
      recognitionRef.current.onend = null
      recognitionRef.current.onresult = null
      recognitionRef.current.onerror = null
      try {
        recognitionRef.current.stop()
      } catch (error) {
        // Ignora errori quando il riconoscimento e' gia' fermo.
      }
      recognitionRef.current = null
    }
  }, [])

  const SpeechRecognitionAPI = window.SpeechRecognition || window.webkitSpeechRecognition
  const speechSupported = !!SpeechRecognitionAPI

  const stopListening = () => {
    shouldKeepListeningRef.current = false
    setIsListening(false)
    if (recognitionRef.current) {
      try {
        recognitionRef.current.stop()
      } catch (error) {
        // Ignora errori quando il riconoscimento e' gia' fermo.
      }
    }
  }

  // Crea una nuova istanza ad ogni avvio (necessario su iOS Safari)
  const startListening = () => {
    if (!SpeechRecognitionAPI) return
    setMicError('')
    shouldKeepListeningRef.current = true
    baseInputRef.current = input
    finalTranscriptRef.current = ''

    const recognition = new SpeechRecognitionAPI()
    recognitionRef.current = recognition
    recognition.lang = 'it-IT'
    recognition.continuous = false
    recognition.interimResults = true

    recognition.onstart = () => {
      setIsListening(true)
    }

    recognition.onend = () => {
      if (shouldKeepListeningRef.current) {
        try {
          recognition.start()
        } catch (error) {
          setTimeout(() => {
            if (!shouldKeepListeningRef.current) return
            try {
              recognition.start()
            } catch (restartError) {
              console.error('Errore riavvio Speech Recognition:', restartError)
              shouldKeepListeningRef.current = false
              setIsListening(false)
            }
          }, 150)
        }
      } else {
        setIsListening(false)
      }
    }

    recognition.onresult = (event) => {
      let interimTranscript = ''
      for (let i = event.resultIndex; i < event.results.length; i++) {
        const chunk = event.results[i][0].transcript
        if (event.results[i].isFinal) {
          finalTranscriptRef.current += chunk
        } else {
          interimTranscript += chunk
        }
      }
      setInput(`${baseInputRef.current}${finalTranscriptRef.current}${interimTranscript}`)
    }

    recognition.onerror = (event) => {
      console.error('Errore Speech Recognition:', event.error)
      if (event.error === 'not-allowed') {
        shouldKeepListeningRef.current = false
        setIsListening(false)
        setMicError('Permesso microfono negato. Abilitalo nelle impostazioni del browser.')
      } else if (event.error === 'network') {
        shouldKeepListeningRef.current = false
        setIsListening(false)
        setMicError('Errore di rete. Controlla la connessione.')
      }
    }

    recognition.start()
  }

  const handleSubmit = (e) => {
    e.preventDefault()
    if (isListening) {
      stopListening()
    }
    const text = input.trim()
    const hasPhotos = selectedPhotos.length > 0

    if ((text || hasPhotos) && !isLoading) {
      onSendMessage({
        text,
        photos: selectedPhotos.map((item) => item.dataUrl)
      })
      setInput('')
      setSelectedPhotos([])
    }
  }

  const handlePhotoSelect = async (event) => {
    const files = Array.from(event.target.files || []).filter((file) => file.type.startsWith('image/'))
    if (!files.length) return

    try {
      const nextPhotos = await Promise.all(files.slice(0, 4).map(async (file) => ({
        name: file.name,
        dataUrl: await resizeImageFile(file)
      })))

      setSelectedPhotos((prev) => {
        const known = new Set(prev.map((item) => item.dataUrl))
        const merged = [...prev]

        nextPhotos.forEach((item) => {
          if (!known.has(item.dataUrl)) {
            known.add(item.dataUrl)
            merged.push(item)
          }
        })

        return merged.slice(-6)
      })
    } catch (error) {
      console.error('Errore selezione foto:', error)
    }
  }

  const removePhoto = (dataUrl) => {
    setSelectedPhotos((prev) => prev.filter((item) => item.dataUrl !== dataUrl))
  }

  const handleMicClick = () => {
    if (!speechSupported) {
      setMicError('Il tuo browser non supporta il riconoscimento vocale.')
      return
    }
    if (isListening) {
      stopListening()
    } else {
      startListening()
    }
  }

  const handleKeyDown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      handleSubmit(e)
    }
  }

  return (
    <div className="input-area">
      <form onSubmit={handleSubmit} className="input-form">
        <textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={handleKeyDown}
          placeholder="Scrivi qui o usa il microfono"
          className="text-input"
          rows={3}
          disabled={isLoading}
        />

        <div className="input-actions">
          {allowPhotoUpload && (
            <>
              {/* Usa label per massima compatibilità mobile (evita .click() programmatico) */}
              <label
                className={`photo-button${isLoading ? ' disabled' : ''}`}
                title="Aggiungi foto di pagine o appunti"
              >
                <span className="action-icon" aria-hidden="true">🖼️</span>
                <span className="action-label">Foto</span>
                <input
                  type="file"
                  accept="image/*"
                  multiple
                  className="photo-input"
                  onChange={handlePhotoSelect}
                  disabled={isLoading}
                />
              </label>
              <label
                className={`camera-button${isLoading ? ' disabled' : ''}`}
                title="Scatta una foto"
              >
                <span className="action-icon" aria-hidden="true">📸</span>
                <span className="action-label">Scatta</span>
                <input
                  type="file"
                  accept="image/*"
                  capture="environment"
                  className="photo-input"
                  onChange={handlePhotoSelect}
                  disabled={isLoading}
                />
              </label>
            </>
          )}

          <button
            type="button"
            onClick={handleMicClick}
            className={`mic-button ${isListening ? 'listening' : ''} ${!speechSupported ? 'mic-unsupported' : ''}`}
            disabled={isLoading}
            title={!speechSupported ? 'Microfono non supportato da questo browser' : isListening ? 'Clicca per interrompere il microfono' : 'Clicca per usare il microfono'}
          >
            <span className="mic-icon action-icon" aria-hidden="true">🎤</span>
            <span className="action-label">Parla</span>
          </button>

          <button
            type="submit"
            className="send-button"
            disabled={isLoading || (!input.trim() && !selectedPhotos.length)}
          >
            {isLoading ? '⏳' : (
              <>
                <img src={sendIcon} alt="Invia" className="send-icon-img action-icon" />
                <span className="action-label">Invia</span>
              </>
            )}
          </button>
        </div>
      </form>

      {allowPhotoUpload && selectedPhotos.length > 0 && (
        <div className="photo-preview-wrap">
          {selectedPhotos.map((photo, idx) => (
            <div className="photo-preview" key={`${photo.dataUrl.slice(0, 24)}-${idx}`}>
              <img src={photo.dataUrl} alt={photo.name || `Foto ${idx + 1}`} />
              <button
                type="button"
                className="photo-remove"
                onClick={() => removePhoto(photo.dataUrl)}
                aria-label={`Rimuovi foto ${idx + 1}`}
              >
                ×
              </button>
            </div>
          ))}
        </div>
      )}

      {isListening && (
        <div className="listening-indicator">
          <div className="pulse"></div>
          <span>In ascolto...</span>
        </div>
      )}

      {micError && (
        <div className="mic-error" role="alert">
          {micError}
        </div>
      )}
    </div>
  )
}

export default InputArea
