/**
 * AccessibilityComm.jsx — Deaf/accessibility communication interface
 *
 * P1 Issue #371: Speech-to-text display (large font), on-screen touch keyboard,
 * text-to-speech responses, and split-screen conversation mode.
 *
 * Subscribes:
 *   /social/speech/transcript      (SpeechTranscript) — user's transcribed speech
 *   /social/conversation/response  (ConversationResponse) — Salty's responses
 *
 * Features:
 *   - Top panel: Large user message display (cyan)
 *   - Bottom panel: Large Salty response display (teal)
 *   - On-screen touch keyboard for manual text input
 *   - Auto-scroll to latest messages
 *   - Clear conversation history
 *   - TTS button for Salty's responses
 *   - Optimized for 7-inch touchscreen (MageDok)
 */

import { useEffect, useRef, useState } from 'react';

const MAX_ENTRIES = 100;
const MIN_FONT_SIZE = 24; // px

function formatTime(ts) {
  return new Date(ts).toLocaleTimeString([], {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
  });
}

// On-screen touch keyboard component
function TouchKeyboard({ onInput, onSend, onClear, value }) {
  const rows = [
    ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
    ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
    ['Z', 'X', 'C', 'V', 'B', 'N', 'M'],
  ];

  const handleKeyClick = (key) => {
    onInput(value + key);
  };

  const handleBackspace = () => {
    onInput(value.slice(0, -1));
  };

  const handleSpace = () => {
    onInput(value + ' ');
  };

  return (
    <div className="flex flex-col gap-1.5 bg-gray-950 border border-gray-800 rounded-lg p-2">
      {/* Text input display */}
      <div className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-lg text-white min-h-12 word-break">
        {value || <span className="text-gray-600">Type your message…</span>}
      </div>

      {/* Keyboard rows */}
      <div className="flex flex-col gap-1">
        {rows.map((row, ri) => (
          <div key={ri} className="flex gap-1 justify-center">
            {row.map((key) => (
              <button
                key={key}
                onClick={() => handleKeyClick(key)}
                className="bg-cyan-700 hover:bg-cyan-600 active:bg-cyan-500 text-white font-bold rounded text-sm flex-1 py-1.5 max-w-12 transition-colors"
              >
                {key}
              </button>
            ))}
          </div>
        ))}

        {/* Bottom row: special keys */}
        <div className="flex gap-1 justify-center">
          <button
            onClick={handleBackspace}
            className="bg-red-700 hover:bg-red-600 active:bg-red-500 text-white font-bold rounded px-3 py-1.5 text-sm transition-colors flex-shrink-0"
          >
            ← Back
          </button>
          <button
            onClick={handleSpace}
            className="bg-blue-700 hover:bg-blue-600 active:bg-blue-500 text-white font-bold rounded px-4 py-1.5 flex-1 transition-colors"
          >
            SPACE
          </button>
          <button
            onClick={onClear}
            className="bg-orange-700 hover:bg-orange-600 active:bg-orange-500 text-white font-bold rounded px-3 py-1.5 text-sm transition-colors flex-shrink-0"
          >
            Clear
          </button>
        </div>
      </div>

      {/* Send button */}
      <button
        onClick={onSend}
        disabled={!value.trim()}
        className="w-full bg-green-600 hover:bg-green-500 disabled:bg-gray-600 disabled:cursor-not-allowed active:bg-green-400 text-white font-bold rounded py-2 text-lg transition-colors"
      >
        SEND MESSAGE
      </button>
    </div>
  );
}

// Large message bubble for user
function UserMessageBubble({ entry }) {
  return (
    <div className="flex flex-col gap-1 mb-2">
      <div className="text-xs text-gray-500 px-2">
        {formatTime(entry.ts)} — {entry.speaker || 'You'} {entry.partial && <span className="text-amber-600">(transcribing…)</span>}
      </div>
      <div className="bg-cyan-950 border-2 border-cyan-600 rounded-lg px-4 py-3 text-cyan-100">
        <p style={{ fontSize: `${MIN_FONT_SIZE}px` }} className="leading-tight break-words whitespace-pre-wrap">
          {entry.text}
        </p>
      </div>
    </div>
  );
}

// Large message bubble for Salty
function SaltyMessageBubble({ entry, onSpeak }) {
  return (
    <div className="flex flex-col gap-1 mb-2">
      <div className="flex items-center justify-between px-2">
        <div className="text-xs text-gray-500">
          {formatTime(entry.ts)} — Salty {entry.partial && <span className="text-amber-600 ml-1">(typing…)</span>}
        </div>
        <button
          onClick={() => onSpeak(entry.text)}
          className="text-xs bg-teal-700 hover:bg-teal-600 active:bg-teal-500 text-white px-2 py-0.5 rounded transition-colors"
        >
          🔊 Speak
        </button>
      </div>
      <div className="bg-teal-950 border-2 border-teal-600 rounded-lg px-4 py-3 text-teal-100">
        <p style={{ fontSize: `${MIN_FONT_SIZE}px` }} className="leading-tight break-words whitespace-pre-wrap">
          {entry.text}
        </p>
      </div>
    </div>
  );
}

export function AccessibilityComm({ subscribe, publish }) {
  const [userMessages, setUserMessages] = useState([]);
  const [saltyMessages, setSaltyMessages] = useState([]);
  const [keyboardInput, setKeyboardInput] = useState('');
  const [autoScroll, setAutoScroll] = useState(true);
  const userBottomRef = useRef(null);
  const saltyBottomRef = useRef(null);

  // Subscribe to user speech transcripts
  useEffect(() => {
    const unsub = subscribe(
      '/social/speech/transcript',
      'saltybot_social_msgs/SpeechTranscript',
      (msg) => {
        setUserMessages((prev) => {
          const entry = {
            id: `h-${msg.header?.stamp?.sec ?? Date.now()}-${msg.turn_id ?? Math.random()}`,
            text: msg.text,
            speaker: msg.speaker_id,
            confidence: msg.confidence,
            partial: msg.is_partial,
            ts: Date.now(),
          };

          // Replace partial with same turn
          if (msg.is_partial) {
            const idx = prev.findLastIndex((e) => e.partial && e.speaker === msg.speaker_id);
            if (idx !== -1) {
              const updated = [...prev];
              updated[idx] = entry;
              return updated;
            }
          } else {
            // Replace trailing partial for same speaker
            const idx = prev.findLastIndex((e) => e.partial && e.speaker === msg.speaker_id);
            if (idx !== -1) {
              const updated = [...prev];
              updated[idx] = { ...entry, id: prev[idx].id };
              return updated.slice(-MAX_ENTRIES);
            }
          }

          return [...prev, entry].slice(-MAX_ENTRIES);
        });
      }
    );
    return unsub;
  }, [subscribe]);

  // Subscribe to Salty responses
  useEffect(() => {
    const unsub = subscribe(
      '/social/conversation/response',
      'saltybot_social_msgs/ConversationResponse',
      (msg) => {
        setSaltyMessages((prev) => {
          const entry = {
            id: `b-${msg.turn_id ?? Math.random()}`,
            text: msg.text,
            speaker: 'Salty',
            partial: msg.is_partial,
            turnId: msg.turn_id,
            ts: Date.now(),
          };

          // Replace streaming partial with same turn_id
          if (msg.turn_id != null) {
            const idx = prev.findLastIndex((e) => e.turnId === msg.turn_id);
            if (idx !== -1) {
              const updated = [...prev];
              updated[idx] = entry;
              return updated;
            }
          }

          return [...prev, entry].slice(-MAX_ENTRIES);
        });
      }
    );
    return unsub;
  }, [subscribe]);

  // Auto-scroll to latest messages
  useEffect(() => {
    if (autoScroll && userBottomRef.current) {
      userBottomRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [userMessages, autoScroll]);

  useEffect(() => {
    if (autoScroll && saltyBottomRef.current) {
      saltyBottomRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [saltyMessages, autoScroll]);

  // Send manual keyboard input
  const handleSendMessage = () => {
    if (!keyboardInput.trim()) return;

    // Publish as a user text input message
    if (publish) {
      publish('/social/text_input', 'std_msgs/String', {
        data: keyboardInput,
      });
    }

    // Clear input
    setKeyboardInput('');
  };

  // Text-to-speech for Salty's message
  const handleSpeak = (text) => {
    if ('speechSynthesis' in window) {
      window.speechSynthesis.cancel(); // Cancel any ongoing speech
      const utterance = new SpeechSynthesisUtterance(text);
      utterance.rate = 0.9; // Slightly slower for clarity
      utterance.pitch = 1.0;
      utterance.volume = 1.0;
      window.speechSynthesis.speak(utterance);
    }
  };

  const handleClear = () => {
    setUserMessages([]);
    setSaltyMessages([]);
    setKeyboardInput('');
  };

  return (
    <div className="flex flex-col h-full gap-4 p-4 bg-gray-900 rounded-lg" style={{ minHeight: '100vh' }}>
      {/* Title & Controls */}
      <div className="flex items-center justify-between bg-gray-950 border border-gray-800 rounded-lg p-3 shrink-0">
        <div className="text-sm font-bold text-cyan-400 tracking-widest">DEAF/ACCESSIBILITY MODE — Issue #371</div>
        <div className="flex items-center gap-2">
          <label className="flex items-center gap-2 cursor-pointer text-xs text-gray-400">
            <input
              type="checkbox"
              checked={autoScroll}
              onChange={(e) => setAutoScroll(e.target.checked)}
              className="accent-cyan-500 w-3 h-3"
            />
            Auto-scroll
          </label>
          <button
            onClick={handleClear}
            className="px-3 py-1 rounded bg-red-900 hover:bg-red-800 text-red-200 text-xs font-bold transition-colors"
          >
            🗑️ Clear All
          </button>
        </div>
      </div>

      {/* Split-screen conversation */}
      <div className="flex-1 gap-4 grid grid-cols-1 lg:grid-cols-2 overflow-hidden">
        {/* User Messages Panel */}
        <div className="flex flex-col overflow-hidden border border-cyan-900 rounded-lg bg-cyan-950 bg-opacity-30">
          <div className="px-3 py-2 bg-cyan-950 border-b border-cyan-900 shrink-0">
            <div className="text-xs font-bold text-cyan-400 tracking-widest">YOUR MESSAGES</div>
            <div className="text-xs text-cyan-700">{userMessages.length} messages</div>
          </div>
          <div className="flex-1 overflow-y-auto p-3 space-y-2">
            {userMessages.length === 0 ? (
              <div className="text-gray-600 text-center py-8 border border-dashed border-gray-800 rounded-lg">
                <p style={{ fontSize: '18px' }}>Waiting for speech…</p>
                <p className="text-xs text-gray-700 mt-2">Or use the keyboard below to type</p>
              </div>
            ) : (
              userMessages.map((entry) => <UserMessageBubble key={entry.id} entry={entry} />)
            )}
            <div ref={userBottomRef} />
          </div>
        </div>

        {/* Salty Response Panel */}
        <div className="flex flex-col overflow-hidden border border-teal-900 rounded-lg bg-teal-950 bg-opacity-30">
          <div className="px-3 py-2 bg-teal-950 border-b border-teal-900 shrink-0">
            <div className="text-xs font-bold text-teal-400 tracking-widest">SALTY'S RESPONSES</div>
            <div className="text-xs text-teal-700">{saltyMessages.length} responses</div>
          </div>
          <div className="flex-1 overflow-y-auto p-3 space-y-2">
            {saltyMessages.length === 0 ? (
              <div className="text-gray-600 text-center py-8 border border-dashed border-gray-800 rounded-lg">
                <p style={{ fontSize: '18px' }}>Waiting for Salty's response…</p>
                <p className="text-xs text-gray-700 mt-2">Salty will display her messages here</p>
              </div>
            ) : (
              saltyMessages.map((entry) => (
                <SaltyMessageBubble
                  key={entry.id}
                  entry={entry}
                  onSpeak={handleSpeak}
                />
              ))
            )}
            <div ref={saltyBottomRef} />
          </div>
        </div>
      </div>

      {/* On-screen touch keyboard */}
      <div className="shrink-0 border border-gray-800 rounded-lg bg-gray-950">
        <TouchKeyboard
          value={keyboardInput}
          onInput={setKeyboardInput}
          onSend={handleSendMessage}
          onClear={() => setKeyboardInput('')}
        />
      </div>

      {/* Footer with instructions */}
      <div className="text-xs text-gray-600 border-t border-gray-800 pt-2 shrink-0">
        <p>💡 <strong>Tips:</strong> Speak clearly for speech-to-text, or use the keyboard below. Click 🔊 to hear Salty's responses aloud.</p>
      </div>
    </div>
  );
}
