/**
 * WorkspaceInput -- Prompt input with @file autocomplete, attachment bar,
 * voice toggle (generic audio capture hook), and data source selection.
 */

import React, { useState, useCallback, useRef, useEffect } from 'react';
import { ProviderMultiSelect } from '../../../components/ProviderSelector';
import type { ProviderSelection } from '../../../components/ProviderSelector';
import { getPageIcon } from '../../../config/pageRegistry';
import { useVoiceStream } from '../../../hooks/useSpeechAudioCapture';
import type { WorkspaceFile, DataSource, FeatureDataSource } from './useWorkspace';

import { useLanguage } from '../../../providers/language/LanguageContext';

const _STT_LANGUAGES = [
  { code: 'de-DE', label: 'Deutsch' },
  { code: 'en-US', label: 'English (US)' },
  { code: 'en-GB', label: 'English (UK)' },
  { code: 'fr-FR', label: 'Francais' },
  { code: 'it-IT', label: 'Italiano' },
  { code: 'es-ES', label: 'Espanol' },
  { code: 'pt-BR', label: 'Portugues' },
  { code: 'nl-NL', label: 'Nederlands' },
  { code: 'pl-PL', label: 'Polski' },
  { code: 'ru-RU', label: 'Russkij' },
  { code: 'ja-JP', label: 'Japanese' },
  { code: 'zh-CN', label: 'Chinese' },
];

interface PendingFile {
  fileId: string;
  fileName: string;
  itemType?: 'file' | 'folder';
}

interface TreeItemDrop {
  id: string;
  type: 'file' | 'folder';
  name: string;
}

interface WorkspaceInputProps {
  instanceId: string;
  onSend: (prompt: string, fileIds?: string[], dataSourceIds?: string[], featureDataSourceIds?: string[], options?: { requireNeutralization?: boolean }) => void;
  isProcessing: boolean;
  onStop: () => void;
  files: WorkspaceFile[];
  dataSources: DataSource[];
  featureDataSources?: FeatureDataSource[];
  pendingFiles?: PendingFile[];
  onRemovePendingFile?: (fileId: string) => void;
  onFileUploadClick?: () => void;
  uploading?: boolean;
  providerSelection?: ProviderSelection;
  onProviderSelectionChange?: (selection: ProviderSelection) => void;
  isMobile?: boolean;
  onTreeItemsDrop?: (items: TreeItemDrop[]) => void;
  onPasteAsFile?: (file: File) => void;
  draftAppend?: string;
  onDraftAppendConsumed?: () => void;
}

export const WorkspaceInput: React.FC<WorkspaceInputProps> = ({ instanceId: _instanceId,
  onSend,
  isProcessing,
  onStop,
  files,
  dataSources,
  featureDataSources = [],
  pendingFiles = [],
  onRemovePendingFile,
  onFileUploadClick,
  uploading = false,
  providerSelection,
  onProviderSelectionChange,
  isMobile = false,
  onTreeItemsDrop,
  onPasteAsFile,
  draftAppend,
  onDraftAppendConsumed,
}) => {
  const { t } = useLanguage();
  const [prompt, setPrompt] = useState('');
  const [showAutocomplete, setShowAutocomplete] = useState(false);
  const [autocompleteFilter, setAutocompleteFilter] = useState('');
  const [treeDropOver, setTreeDropOver] = useState(false);
  const [voiceActive, setVoiceActive] = useState(false);
  const [voiceLanguage, setVoiceLanguage] = useState('de-DE');
  const [showLangPicker, setShowLangPicker] = useState(false);
  const _sttPrefsLoaded = useRef(false);
  const [attachedFileIds, setAttachedFileIds] = useState<string[]>([]);
  const [attachedDataSourceIds, setAttachedDataSourceIds] = useState<string[]>([]);
  const [attachedFeatureDataSourceIds, setAttachedFeatureDataSourceIds] = useState<string[]>([]);
  const [neutralizeActive, setNeutralizeActive] = useState(false);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    if (draftAppend) {
      setPrompt(prev => prev + (prev ? '\n' : '') + draftAppend);
      onDraftAppendConsumed?.();
    }
  }, [draftAppend, onDraftAppendConsumed]);

  const promptBeforeVoiceRef = useRef('');
  const finalizedTextRef = useRef('');
  const currentInterimRef = useRef('');

  useEffect(() => {
    if (_sttPrefsLoaded.current) return;
    _sttPrefsLoaded.current = true;
    fetch('/api/voice/preferences', { credentials: 'include' })
      .then(r => r.ok ? r.json() : null)
      .then(data => { if (data?.sttLanguage) setVoiceLanguage(data.sttLanguage); })
      .catch(() => {});
  }, []);

  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])];
    const options = neutralizeActive ? { requireNeutralization: true } : undefined;
    onSend(trimmed, allFileIds, attachedDataSourceIds, attachedFeatureDataSourceIds, options);
    setPrompt('');
    setShowAutocomplete(false);
    setShowSourcePicker(false);
    setAttachedFileIds([]);
  }, [prompt, isProcessing, _extractFileRefs, attachedFileIds, attachedDataSourceIds, attachedFeatureDataSourceIds, neutralizeActive, 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 [showSourcePicker, setShowSourcePicker] = useState(false);

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

  const _toggleFeatureDataSource = useCallback((fdsId: string) => {
    setAttachedFeatureDataSourceIds(prev =>
      prev.includes(fdsId) ? prev.filter(id => id !== fdsId) : [...prev, fdsId],
    );
  }, []);

  const _buildPromptFromRefs = useCallback(() => {
    const parts = [
      promptBeforeVoiceRef.current,
      finalizedTextRef.current,
      currentInterimRef.current,
    ].filter(Boolean);
    return parts.join(' ');
  }, []);

  const voiceStream = useVoiceStream({
    onFinal: (text) => {
      finalizedTextRef.current = finalizedTextRef.current
        ? `${finalizedTextRef.current} ${text}`
        : text;
      currentInterimRef.current = '';
      setPrompt(_buildPromptFromRefs());
    },
    onInterim: (text) => {
      currentInterimRef.current = text;
      setPrompt(_buildPromptFromRefs());
    },
    onError: (error) => {
      console.warn('Workspace voice stream error', error);
    },
  });

  const _stopVoiceCapture = useCallback(() => {
    if (currentInterimRef.current) {
      finalizedTextRef.current = finalizedTextRef.current
        ? `${finalizedTextRef.current} ${currentInterimRef.current}`
        : currentInterimRef.current;
      currentInterimRef.current = '';
    }
    setPrompt(_buildPromptFromRefs());
    voiceStream.stop();
    setVoiceActive(false);
  }, [voiceStream, _buildPromptFromRefs]);

  const _toggleVoice = useCallback(async () => {
    if (voiceActive) {
      _stopVoiceCapture();
      return;
    }

    promptBeforeVoiceRef.current = prompt;
    finalizedTextRef.current = '';
    currentInterimRef.current = '';
    try {
      setVoiceActive(true);
      await voiceStream.start(voiceLanguage);
    } catch {
      setVoiceActive(false);
    }
  }, [voiceActive, prompt, voiceStream, voiceLanguage, _stopVoiceCapture]);

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

  const hasAttachments = attachedFileIds.length > 0 || attachedDataSourceIds.length > 0 || attachedFeatureDataSourceIds.length > 0;
  const _horizontalPadding = isMobile ? 12 : 24;
  const _controlSize = isMobile ? 38 : 40;

  const _handlePaste = useCallback((e: React.ClipboardEvent<HTMLTextAreaElement>) => {
    if (!onPasteAsFile) return;
    const text = e.clipboardData.getData('text/plain');
    if (text && text.length >= 1000) {
      e.preventDefault();
      const blob = new Blob([text], { type: 'text/plain' });
      const file = new File([blob], `pasted-text-${Date.now()}.txt`, { type: 'text/plain' });
      onPasteAsFile(file);
    }
  }, [onPasteAsFile]);

  const _handlePromptDragOver = useCallback((e: React.DragEvent) => {
    if (
      e.dataTransfer.types.includes('application/tree-items') ||
      e.dataTransfer.types.includes('application/chat-id')
    ) {
      e.preventDefault();
      e.dataTransfer.dropEffect = 'copy';
      setTreeDropOver(true);
    }
  }, []);

  const _handlePromptDragLeave = useCallback(() => setTreeDropOver(false), []);

  const _handlePromptDrop = useCallback((e: React.DragEvent) => {
    setTreeDropOver(false);

    const chatId = e.dataTransfer.getData('application/chat-id');
    if (chatId) {
      e.preventDefault();
      e.stopPropagation();
      const chatLabel = e.dataTransfer.getData('text/plain');
      const ref = chatLabel ? `[Chat: ${chatLabel}]` : `[Chat: ${chatId.slice(0, 8)}]`;
      setPrompt(prev => (prev ? `${prev} ${ref}` : ref));
      return;
    }

    const treeItemsJson = e.dataTransfer.getData('application/tree-items');
    if (treeItemsJson && onTreeItemsDrop) {
      e.preventDefault();
      e.stopPropagation();
      const items: TreeItemDrop[] = JSON.parse(treeItemsJson);
      onTreeItemsDrop(items);
    }
  }, [onTreeItemsDrop]);

  return (
    <div
      style={{
        borderTop: '1px solid var(--border-color, #e0e0e0)',
        position: 'relative',
        flexShrink: 0,
        outline: treeDropOver ? '2px dashed var(--primary-color, #F25843)' : 'none',
        background: treeDropOver ? 'var(--primary-dark-bg, rgba(242, 88, 67, 0.08))' : undefined,
        transition: 'background 0.15s, outline 0.15s',
      }}
      onDragOver={_handlePromptDragOver}
      onDragLeave={_handlePromptDragLeave}
      onDrop={_handlePromptDrop}
    >
      {/* Pending uploaded files */}
      {pendingFiles.length > 0 && (
        <div style={{
          padding: `6px ${_horizontalPadding}px`,
          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: pf.itemType === 'folder' ? '#e3f2fd' : '#fff3e0',
                color: pf.itemType === 'folder' ? '#1565c0' : '#e65100',
                fontWeight: 500,
                border: `1px solid ${pf.itemType === 'folder' ? '#bbdefb' : '#ffe0b2'}`,
              }}
            >
              {pf.itemType === 'folder' ? '📁' : '📎'} {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 ${_horizontalPadding}px`,
          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 || ds?.path || dsId}
                <button
                  onClick={() => _removeAttachedDataSource(dsId)}
                  style={{
                    border: 'none', background: 'none', cursor: 'pointer',
                    fontSize: 12, color: '#2e7d32', padding: 0, lineHeight: 1,
                  }}
                >
                  ×
                </button>
              </span>
            );
          })}
          {attachedFeatureDataSourceIds.map(fdsId => {
            const fds = featureDataSources.find(d => d.id === fdsId);
            const fdsIcon = fds ? getPageIcon(`feature.${fds.featureCode}`) : null;
            return (
              <span
                key={fdsId}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  padding: '3px 8px', borderRadius: 12, fontSize: 11,
                  background: '#f3e5f5', color: '#7b1fa2', fontWeight: 500,
                }}
              >
                <span style={{ display: 'flex', alignItems: 'center', fontSize: 12 }}>{fdsIcon || '\uD83D\uDDC3\uFE0F'}</span>
                {fds?.label || fdsId} – {fds?.tableName || ''}
                <button
                  onClick={() => _toggleFeatureDataSource(fdsId)}
                  style={{
                    border: 'none', background: 'none', cursor: 'pointer',
                    fontSize: 12, color: '#7b1fa2', padding: 0, lineHeight: 1,
                  }}
                >
                  ×
                </button>
              </span>
            );
          })}
        </div>
      )}

      {/* Autocomplete dropdown */}
      {showAutocomplete && filteredFiles.length > 0 && (
        <div style={{
          position: 'absolute',
          bottom: '100%',
          left: _horizontalPadding,
          right: _horizontalPadding,
          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 ${_horizontalPadding}px 12px`,
        display: 'flex',
        gap: 8,
        alignItems: isMobile ? 'stretch' : 'flex-end',
        flexWrap: isMobile ? 'wrap' : 'nowrap',
      }}>
        <textarea
          ref={textareaRef}
          value={prompt}
          onChange={_handleChange}
          onKeyDown={_handleKeyDown}
          onPaste={_handlePaste}
          placeholder={t('Geben Sie eine Nachricht ein, verwenden Sie @file für Dateien')}
          disabled={isProcessing}
          style={{
            flex: 1,
            minHeight: isMobile ? 44 : 40,
            maxHeight: 120,
            resize: 'vertical',
            padding: '10px 14px',
            borderRadius: 8,
            border: '1px solid var(--border-color, #ccc)',
            fontSize: 14,
            fontFamily: 'inherit',
            outline: 'none',
            flexBasis: isMobile ? '100%' : undefined,
          }}
          rows={1}
        />

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

        {/* Source picker removed — data sources are now attached directly from the UDB Sources/Files tabs via "send to chat" buttons */}

        {onProviderSelectionChange && providerSelection && (
          <ProviderMultiSelect
            selection={providerSelection}
            onChange={onProviderSelectionChange}
            showLabel={false}
            disabled={isProcessing}
          />
        )}

        <div style={{ position: 'relative', display: 'flex', gap: 2 }}>
          <button
            onClick={() => setShowLangPicker(prev => !prev)}
            title={t('Sprache wählen')}
            style={{
              height: _controlSize, borderRadius: '8px 0 0 8px', border: '1px solid var(--border-color, #ddd)',
              borderRight: 'none',
              background: 'var(--secondary-bg, #f5f5f5)',
              color: '#666', cursor: 'pointer', fontSize: 10, padding: '0 6px',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}
          >
            {voiceLanguage.split('-')[0].toUpperCase()}
          </button>
          <button
            onClick={_toggleVoice}
            title={voiceActive ? t('Aufnahme stoppen') : t('Sprachaufnahme starten')}
            style={{
              width: _controlSize, height: _controlSize, borderRadius: '0 8px 8px 0', border: 'none',
              background: voiceActive ? '#f44336' : 'var(--secondary-bg, #f5f5f5)',
              color: voiceActive ? '#fff' : '#666',
              cursor: 'pointer', fontSize: 18, display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}
          >
            {voiceActive ? '■' : '\uD83C\uDFA4'}
          </button>
          {showLangPicker && (
            <div style={{
              position: 'absolute', bottom: '100%', right: 0, marginBottom: 4,
              background: '#fff', border: '1px solid var(--border-color, #e0e0e0)',
              borderRadius: 8, boxShadow: '0 -2px 8px rgba(0,0,0,0.1)', zIndex: 20,
              maxHeight: 240, overflowY: 'auto', minWidth: 160,
            }}>
              {_STT_LANGUAGES.map(lang => (
                <div
                  key={lang.code}
                  onClick={() => {
                    setVoiceLanguage(lang.code);
                    setShowLangPicker(false);
                    fetch('/api/voice/preferences', { method: 'PUT', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sttLanguage: lang.code }) }).catch(() => {});
                  }}
                  style={{
                    padding: '8px 12px', cursor: 'pointer', fontSize: 13,
                    background: lang.code === voiceLanguage ? 'var(--primary-color, #F25843)' : 'transparent',
                    color: lang.code === voiceLanguage ? '#fff' : 'var(--text-primary, #333)',
                  }}
                  onMouseEnter={e => { if (lang.code !== voiceLanguage) e.currentTarget.style.background = 'var(--bg-secondary, #f5f5f5)'; }}
                  onMouseLeave={e => { if (lang.code !== voiceLanguage) e.currentTarget.style.background = ''; }}
                >
                  {lang.label} ({lang.code})
                </div>
              ))}
            </div>
          )}
        </div>

        <button
          onClick={() => setNeutralizeActive(v => !v)}
          title={neutralizeActive ? t('Neutralisierung aktiv, klicken zum Deaktivieren') : t('Neutralisierung aus, klicken zum Aktivieren')}
          style={{
            padding: '8px 10px', borderRadius: 8, border: '1px solid',
            borderColor: neutralizeActive ? '#166534' : 'var(--border-color, #d1d5db)',
            background: neutralizeActive ? '#dcfce7' : 'transparent',
            cursor: 'pointer', fontSize: '1rem', lineHeight: 1,
            opacity: neutralizeActive ? 1 : 0.5,
            transition: 'all 0.15s',
          }}
        >
          🔒
        </button>

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