/**
 * WorkspaceInput -- Prompt input with @file autocomplete, attachment bar,
 * voice toggle, and data source selection.
 */

import React, { useState, useCallback, useRef } from 'react';
import { ProviderMultiSelect } from '../../../components/ProviderSelector';
import type { WorkspaceFile, DataSource } from './useWorkspace';

interface PendingFile {
  fileId: string;
  fileName: string;
}

interface WorkspaceInputProps {
  instanceId: string;
  onSend: (prompt: string, fileIds?: string[], dataSourceIds?: string[]) => void;
  isProcessing: boolean;
  onStop: () => void;
  files: WorkspaceFile[];
  dataSources: DataSource[];
  pendingFiles?: PendingFile[];
  onRemovePendingFile?: (fileId: string) => void;
  onFileUploadClick?: () => void;
  uploading?: boolean;
  selectedProviders?: string[];
  onProvidersChange?: (providers: string[]) => void;
}

export const WorkspaceInput: React.FC<WorkspaceInputProps> = ({
  instanceId,
  onSend,
  isProcessing,
  onStop,
  files,
  dataSources,
  pendingFiles = [],
  onRemovePendingFile,
  onFileUploadClick,
  uploading = false,
  selectedProviders = [],
  onProvidersChange,
}) => {
  const [prompt, setPrompt] = useState('');
  const [showAutocomplete, setShowAutocomplete] = useState(false);
  const [autocompleteFilter, setAutocompleteFilter] = useState('');
  const [voiceActive, setVoiceActive] = useState(false);
  const [attachedFileIds, setAttachedFileIds] = useState<string[]>([]);
  const [attachedDataSourceIds, setAttachedDataSourceIds] = useState<string[]>([]);
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const chunksRef = useRef<Blob[]>([]);

  const _extractFileRefs = useCallback(
    (text: string): string[] => {
      const pattern = /@([\w.\-]+)/g;
      const matched: string[] = [];
      let match;
      while ((match = pattern.exec(text)) !== null) {
        const ref = match[1];
        const file = files.find(
          f => f.fileName === ref || f.fileName.toLowerCase() === ref.toLowerCase(),
        );
        if (file && !matched.includes(file.id)) {
          matched.push(file.id);
        }
      }
      return matched;
    },
    [files],
  );

  const _handleSend = useCallback(() => {
    const trimmed = prompt.trim();
    if (!trimmed || isProcessing) return;
    const inlineFileIds = _extractFileRefs(trimmed);
    const allFileIds = [...new Set([...attachedFileIds, ...inlineFileIds])];
    onSend(trimmed, allFileIds, attachedDataSourceIds);
    setPrompt('');
    setShowAutocomplete(false);
    setAttachedFileIds([]);
    setAttachedDataSourceIds([]);
  }, [prompt, isProcessing, _extractFileRefs, attachedFileIds, attachedDataSourceIds, onSend]);

  const _handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        _handleSend();
      }
    },
    [_handleSend],
  );

  const _handleChange = useCallback(
    (e: React.ChangeEvent<HTMLTextAreaElement>) => {
      const value = e.target.value;
      setPrompt(value);
      const cursorPos = e.target.selectionStart;
      const textBeforeCursor = value.slice(0, cursorPos);
      const atMatch = textBeforeCursor.match(/@([\w.\-]*)$/);
      if (atMatch) {
        setAutocompleteFilter(atMatch[1].toLowerCase());
        setShowAutocomplete(true);
      } else {
        setShowAutocomplete(false);
      }
    },
    [],
  );

  const _insertFileRef = useCallback(
    (fileName: string) => {
      const textarea = textareaRef.current;
      if (!textarea) return;
      const cursorPos = textarea.selectionStart;
      const textBefore = prompt.slice(0, cursorPos);
      const textAfter = prompt.slice(cursorPos);
      const atStart = textBefore.lastIndexOf('@');
      const newText = textBefore.slice(0, atStart) + `@${fileName} ` + textAfter;
      setPrompt(newText);
      setShowAutocomplete(false);
      textarea.focus();
    },
    [prompt],
  );

  const _removeAttachedFile = useCallback((fileId: string) => {
    setAttachedFileIds(prev => prev.filter(id => id !== fileId));
  }, []);

  const _removeAttachedDataSource = useCallback((dsId: string) => {
    setAttachedDataSourceIds(prev => prev.filter(id => id !== dsId));
  }, []);

  const _toggleVoice = useCallback(async () => {
    if (voiceActive) {
      mediaRecorderRef.current?.stop();
      setVoiceActive(false);
      return;
    }
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      const recorder = new MediaRecorder(stream);
      chunksRef.current = [];
      recorder.ondataavailable = (e) => chunksRef.current.push(e.data);
      recorder.onstop = async () => {
        stream.getTracks().forEach(t => t.stop());
        const blob = new Blob(chunksRef.current, { type: 'audio/webm' });
        try {
          const formData = new FormData();
          formData.append('audio', blob, 'voice.webm');
          const res = await fetch(`/api/workspace/${instanceId}/voice/transcribe`, {
            method: 'POST',
            body: formData,
          });
          const data = await res.json();
          if (data.text) {
            setPrompt(prev => prev + (prev ? ' ' : '') + data.text);
          }
        } catch (err) {
          console.error('Voice transcription failed:', err);
        }
      };
      recorder.start();
      mediaRecorderRef.current = recorder;
      setVoiceActive(true);
    } catch (err) {
      console.error('Microphone access denied:', err);
    }
  }, [voiceActive, instanceId]);

  const filteredFiles = showAutocomplete
    ? files.filter(f => f.fileName.toLowerCase().includes(autocompleteFilter))
    : [];

  const hasAttachments = attachedFileIds.length > 0 || attachedDataSourceIds.length > 0;

  return (
    <div style={{
      borderTop: '1px solid var(--border-color, #e0e0e0)',
      position: 'relative',
      flexShrink: 0,
    }}>
      {/* Pending uploaded files */}
      {pendingFiles.length > 0 && (
        <div style={{
          padding: '6px 24px',
          display: 'flex',
          gap: 6,
          flexWrap: 'wrap',
          borderBottom: '1px solid var(--border-color, #f0f0f0)',
          background: 'var(--bg-secondary, #fafafa)',
        }}>
          {pendingFiles.map(pf => (
            <span
              key={pf.fileId}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 4,
                padding: '3px 8px', borderRadius: 12, fontSize: 11,
                background: '#fff3e0', color: '#e65100', fontWeight: 500,
                border: '1px solid #ffe0b2',
              }}
            >
              📎 {pf.fileName.length > 25 ? pf.fileName.slice(0, 25) + '...' : pf.fileName}
              {onRemovePendingFile && (
                <button
                  onClick={() => onRemovePendingFile(pf.fileId)}
                  style={{
                    border: 'none', background: 'none', cursor: 'pointer',
                    fontSize: 12, color: '#e65100', padding: 0, lineHeight: 1,
                  }}
                >
                  ×
                </button>
              )}
            </span>
          ))}
        </div>
      )}

      {/* Attachment bar */}
      {hasAttachments && (
        <div style={{
          padding: '6px 24px',
          display: 'flex',
          gap: 6,
          flexWrap: 'wrap',
          borderBottom: '1px solid var(--border-color, #f0f0f0)',
          background: '#fafafa',
        }}>
          {attachedFileIds.map(fId => {
            const file = files.find(f => f.id === fId);
            return (
              <span
                key={fId}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  padding: '3px 8px', borderRadius: 12, fontSize: 11,
                  background: '#e3f2fd', color: '#1565c0', fontWeight: 500,
                }}
              >
                📄 {file?.fileName || fId}
                <button
                  onClick={() => _removeAttachedFile(fId)}
                  style={{
                    border: 'none', background: 'none', cursor: 'pointer',
                    fontSize: 12, color: '#1565c0', padding: 0, lineHeight: 1,
                  }}
                >
                  ×
                </button>
              </span>
            );
          })}
          {attachedDataSourceIds.map(dsId => {
            const ds = dataSources.find(d => d.id === dsId);
            return (
              <span
                key={dsId}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  padding: '3px 8px', borderRadius: 12, fontSize: 11,
                  background: '#e8f5e9', color: '#2e7d32', fontWeight: 500,
                }}
              >
                🔗 {ds?.label || dsId}
                <button
                  onClick={() => _removeAttachedDataSource(dsId)}
                  style={{
                    border: 'none', background: 'none', cursor: 'pointer',
                    fontSize: 12, color: '#2e7d32', padding: 0, lineHeight: 1,
                  }}
                >
                  ×
                </button>
              </span>
            );
          })}
        </div>
      )}

      {/* Autocomplete dropdown */}
      {showAutocomplete && filteredFiles.length > 0 && (
        <div style={{
          position: 'absolute',
          bottom: '100%',
          left: 24,
          right: 24,
          maxHeight: 200,
          overflowY: 'auto',
          background: '#fff',
          border: '1px solid var(--border-color, #e0e0e0)',
          borderRadius: 8,
          boxShadow: '0 -2px 8px rgba(0,0,0,0.1)',
          zIndex: 10,
        }}>
          {filteredFiles.slice(0, 10).map(f => (
            <div
              key={f.id}
              onClick={() => _insertFileRef(f.fileName)}
              style={{
                padding: '8px 12px',
                cursor: 'pointer',
                fontSize: 13,
                borderBottom: '1px solid #f0f0f0',
              }}
              onMouseEnter={e => (e.currentTarget.style.background = '#f5f5f5')}
              onMouseLeave={e => (e.currentTarget.style.background = '')}
            >
              @{f.fileName}
              <span style={{ color: '#999', marginLeft: 8, fontSize: 11 }}>
                {f.mimeType} · {(f.fileSize / 1024).toFixed(1)}KB
              </span>
            </div>
          ))}
        </div>
      )}

      {/* Main input row */}
      <div style={{ padding: '8px 24px 12px', display: 'flex', gap: 8, alignItems: 'flex-end' }}>
        <textarea
          ref={textareaRef}
          value={prompt}
          onChange={_handleChange}
          onKeyDown={_handleKeyDown}
          placeholder="Type a message... Use @filename to reference files"
          disabled={isProcessing}
          style={{
            flex: 1,
            minHeight: 40,
            maxHeight: 120,
            resize: 'vertical',
            padding: '10px 14px',
            borderRadius: 8,
            border: '1px solid var(--border-color, #ccc)',
            fontSize: 14,
            fontFamily: 'inherit',
            outline: 'none',
          }}
          rows={1}
        />

        <button
          onClick={onFileUploadClick}
          disabled={uploading || isProcessing}
          title="Datei anhängen"
          style={{
            width: 40, height: 40, borderRadius: 8, border: '1px solid var(--border-color, #ddd)',
            background: 'var(--secondary-bg, #f5f5f5)',
            color: uploading ? '#1976d2' : '#666',
            cursor: uploading || isProcessing ? 'not-allowed' : 'pointer',
            fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center',
            opacity: isProcessing ? 0.5 : 1,
          }}
        >
          {uploading ? '...' : '+'}
        </button>

        {onProvidersChange && (
          <ProviderMultiSelect
            selectedProviders={selectedProviders}
            onChange={onProvidersChange}
            showLabel={false}
            excludeByDefault={['privatellm']}
            disabled={isProcessing}
          />
        )}

        <button
          onClick={_toggleVoice}
          title={voiceActive ? 'Stop recording' : 'Voice input'}
          style={{
            width: 40, height: 40, borderRadius: 8, border: 'none',
            background: voiceActive ? '#f44336' : 'var(--secondary-bg, #f5f5f5)',
            color: voiceActive ? '#fff' : '#666',
            cursor: 'pointer', fontSize: 18, display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}
        >
          {voiceActive ? '■' : '🎤'}
        </button>

        {isProcessing ? (
          <button
            onClick={onStop}
            style={{
              padding: '10px 20px', borderRadius: 8, border: 'none',
              background: '#f44336', color: '#fff', cursor: 'pointer', fontWeight: 600,
            }}
          >
            Stop
          </button>
        ) : (
          <button
            onClick={_handleSend}
            disabled={!prompt.trim()}
            style={{
              padding: '10px 20px', borderRadius: 8, border: 'none',
              background: prompt.trim() ? 'var(--primary-color, #1976d2)' : '#ccc',
              color: '#fff', cursor: prompt.trim() ? 'pointer' : 'default', fontWeight: 600,
            }}
          >
            Send
          </button>
        )}
      </div>
    </div>
  );
};
