/**
 * WorkspacePage -- Unified AI Workspace
 *
 * 3-column layout:
 *   Left sidebar:  UnifiedDataBar (Chats, Files, Sources)
 *   Center:        ChatStream + WorkspaceInput
 *   Right sidebar: FilePreview, ToolActivityLog
 */

import React, { useState, useCallback, useRef, useEffect } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { useCurrentInstance } from '../../../hooks/useCurrentInstance';
import { useFileOperations } from '../../../hooks/useFiles';
import { useWorkspace } from './useWorkspace';
import { ChatStream } from './ChatStream';
import { WorkspaceInput } from './WorkspaceInput';
import { FilePreview } from './FilePreview';
import { ToolActivityLog } from './ToolActivityLog';
import { UnifiedDataBar } from '../../../components/UnifiedDataBar';
import type { UdbContext, UdbTab, AddToChat_FileItem, AddToChat_FeatureSource } from '../../../components/UnifiedDataBar';
import api from '../../../api';
import { _defaultProviderSelection, _toBackendProviders } from '../../../components/ProviderSelector';
import type { ProviderSelection } from '../../../components/ProviderSelector';
import { useBilling } from '../../../hooks/useBilling';
import { useLanguage } from '../../../providers/language/LanguageContext';

function _useResizable(initialWidth: number, minWidth: number, maxWidth: number) {
  const [width, setWidth] = useState(initialWidth);
  const dragging = useRef(false);
  const startX = useRef(0);
  const startW = useRef(0);

  const _onMouseDown = useCallback((e: React.MouseEvent, direction: 1 | -1 = 1) => {
    e.preventDefault();
    dragging.current = true;
    startX.current = e.clientX;
    startW.current = width;

    const _onMouseMove = (ev: MouseEvent) => {
      if (!dragging.current) return;
      const delta = (ev.clientX - startX.current) * direction;
      setWidth(Math.max(minWidth, Math.min(maxWidth, startW.current + delta)));
    };
    const _onMouseUp = () => {
      dragging.current = false;
      document.removeEventListener('mousemove', _onMouseMove);
      document.removeEventListener('mouseup', _onMouseUp);
      document.body.style.cursor = '';
      document.body.style.userSelect = '';
    };
    document.addEventListener('mousemove', _onMouseMove);
    document.addEventListener('mouseup', _onMouseUp);
    document.body.style.cursor = 'col-resize';
    document.body.style.userSelect = 'none';
  }, [width, minWidth, maxWidth]);

  return { width, onMouseDown: _onMouseDown };
}
type RightTab = 'activity' | 'preview';

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

interface WorkspacePageProps {
  persistentInstanceId?: string;
}

export const WorkspacePage: React.FC<WorkspacePageProps> = ({ persistentInstanceId }) => {
  const { t } = useLanguage();
  const { instance } = useCurrentInstance();
  const instanceId = persistentInstanceId || instance?.id || '';
  const workspace = useWorkspace(instanceId);
  const fileOps = useFileOperations();
  const navigate = useNavigate();
  const { mandateId, featureCode, instanceId: routeInstanceId } = useParams<{
    mandateId: string; featureCode: string; instanceId: string;
  }>();
  const [leftCollapsed, setLeftCollapsed] = useState(false);
  const [rightCollapsed, setRightCollapsed] = useState(false);
  const _leftResize = _useResizable(280, 200, 450);
  const _rightResize = _useResizable(320, 200, 500);
  const [rightTab, setRightTab] = useState<RightTab>('activity');
  const [udbTab, setUdbTab] = useState<UdbTab>('chats');
  const [selectedFileId, setSelectedFileId] = useState<string | null>(null);
  const [pendingFiles, setPendingFiles] = useState<PendingFile[]>([]);
  const [providerSelection, setProviderSelection] = useState<ProviderSelection>(_defaultProviderSelection());
  const { allowedProviders } = useBilling();
  const [isDragOver, setIsDragOver] = useState(false);
  const [draftAppend, setDraftAppend] = useState('');
  const dragCounterRef = useRef(0);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [searchParams, setSearchParams] = useSearchParams();
  const autoStartHandled = useRef(false);
  const [isMobile, setIsMobile] = useState<boolean>(() =>
    typeof window !== 'undefined' ? window.innerWidth <= 1024 : false,
  );
  const [mobileLeftOpen, setMobileLeftOpen] = useState(false);
  const [mobileRightOpen, setMobileRightOpen] = useState(false);

  useEffect(() => {
    const _handleResize = () => {
      setIsMobile(window.innerWidth <= 1024);
    };
    _handleResize();
    window.addEventListener('resize', _handleResize);
    return () => window.removeEventListener('resize', _handleResize);
  }, []);

  useEffect(() => {
    if (!isMobile) {
      setMobileLeftOpen(false);
      setMobileRightOpen(false);
    }
  }, [isMobile]);

  useEffect(() => {
    if (autoStartHandled.current || !instanceId || workspace.isProcessing) return;
    const prompt = searchParams.get('prompt');
    const autoStart = searchParams.get('autoStart') === 'true';
    if (prompt) {
      autoStartHandled.current = true;
      setSearchParams({}, { replace: true });
      if (autoStart) {
        const resolvedProviders = _toBackendProviders(providerSelection, allowedProviders);
        workspace.sendMessage(prompt, [], [], resolvedProviders, []);
      } else {
        setDraftAppend(prompt);
      }
    }
  }, [instanceId, searchParams, setSearchParams, workspace, providerSelection, allowedProviders]);

  const _uploadAndAttach = useCallback(async (file: File) => {
    const result = await fileOps.handleFileUpload(file, undefined, instanceId);
    if (result.success && result.fileData) {
      const data = result.fileData.file || result.fileData;
      if (data?.id) {
        setPendingFiles(prev => [...prev, { fileId: data.id, fileName: data.fileName || file.name }]);
      }
      workspace.refreshFiles();
    }
  }, [fileOps, workspace, instanceId]);

  const _handleDragEnter = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    dragCounterRef.current++;
    if (e.dataTransfer.types.includes('Files')) setIsDragOver(true);
  }, []);

  const _handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    dragCounterRef.current--;
    if (dragCounterRef.current === 0) setIsDragOver(false);
  }, []);

  const _handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
  }, []);

  const _handleDrop = useCallback(async (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    dragCounterRef.current = 0;
    setIsDragOver(false);

    const chatId = e.dataTransfer.getData('application/chat-id');
    if (chatId) {
      try {
        const res = await api.post(`/api/workspace/${instanceId}/resolve-rag`, { chatId });
        const body = res.data ?? {};
        if (body.summary) {
          setDraftAppend(body.summary);
        }
      } catch (err) {
        console.error('RAG resolve failed for dropped chat:', err);
      }
      return;
    }

    const droppedFiles = e.dataTransfer.files;
    if (droppedFiles.length > 0) {
      for (const file of Array.from(droppedFiles)) {
        await _uploadAndAttach(file);
      }
    }
  }, [_uploadAndAttach, instanceId, workspace]);

  const _handleFileInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files.length > 0) {
      Array.from(e.target.files).forEach(file => _uploadAndAttach(file));
      e.target.value = '';
    }
  }, [_uploadAndAttach]);

  const _handleRemovePendingFile = useCallback((fileId: string) => {
    setPendingFiles(prev => prev.filter(f => f.fileId !== fileId));
  }, []);

  const _handleTreeItemsDrop = useCallback((items: Array<{ id: string; type: 'file' | 'folder'; name: string }>) => {
    setPendingFiles(prev => {
      const existing = new Set(prev.map(f => f.fileId));
      const toAdd: PendingFile[] = [];
      for (const item of items) {
        if (!existing.has(item.id)) {
          toAdd.push({ fileId: item.id, fileName: item.name, itemType: item.type });
          existing.add(item.id);
        }
      }
      return [...prev, ...toAdd];
    });
  }, []);

  if (!instanceId) {
    return (
      <div style={{ padding: 32, textAlign: 'center', color: '#999' }}>
        {t('Keine Workspace-Instanz ausgewählt.')}
      </div>
    );
  }

  const _handleFileSelect = (fileId: string) => {
    setSelectedFileId(fileId);
    setRightTab('preview');
    setRightCollapsed(false);
    if (isMobile) {
      setMobileRightOpen(true);
    }
  };

  const _handleConversationSelect = (wfId: string) => {
    workspace.loadWorkflow(wfId);
  };

  const tabButtonStyle = (active: boolean): React.CSSProperties => ({
    flex: 1,
    padding: '6px 0',
    border: 'none',
    borderBottom: active ? '2px solid var(--primary-color, #F25843)' : '2px solid transparent',
    background: 'none',
    cursor: 'pointer',
    fontSize: 11,
    fontWeight: active ? 600 : 400,
    color: active ? 'var(--primary-color, #F25843)' : 'var(--text-tertiary, #888)',
    textTransform: 'uppercase' as const,
  });

  const _handleRenameChat = useCallback(async (chatId: string, newName: string) => {
    try {
      await api.patch(`/api/workspace/${instanceId}/workflows/${chatId}`, { name: newName });
    } catch (err) {
      console.error('Failed to rename chat:', err);
    }
  }, [instanceId]);

  const _handleDeleteChat = useCallback(async (chatId: string) => {
    try {
      await api.delete(`/api/workspace/${instanceId}/workflows/${chatId}`);
      if (workspace.workflowId === chatId) {
        workspace.resetToNew();
      }
    } catch (err) {
      console.error('Failed to delete chat:', err);
    }
  }, [instanceId, workspace]);

  const _udbContext: UdbContext = {
    instanceId: instanceId,
    mandateId: mandateId,
    featureInstanceId: instanceId,
  };

  const _handleSourcesChanged = useCallback(() => {
    workspace.refreshDataSources();
    workspace.refreshFeatureDataSources();
  }, [workspace]);

  const _handleSendToChat_Files = useCallback((items: AddToChat_FileItem[]) => {
    setPendingFiles(prev => {
      const existing = new Set(prev.map(f => f.fileId));
      const toAdd: PendingFile[] = [];
      for (const item of items) {
        if (!existing.has(item.id)) {
          toAdd.push({ fileId: item.id, fileName: item.name, itemType: item.type });
          existing.add(item.id);
        }
      }
      return [...prev, ...toAdd];
    });
  }, []);

  const [pendingAttachFdsId, setPendingAttachFdsId] = useState<string>('');

  const _handleSendToChat_FeatureSource = useCallback(async (params: AddToChat_FeatureSource) => {
    try {
      const res = await api.post(`/api/workspace/${instanceId}/feature-datasources`, {
        featureInstanceId: params.featureInstanceId,
        featureCode: params.featureCode,
        tableName: params.tableName || '',
        objectKey: params.objectKey,
        label: params.label,
      });
      // Backend response shape parity with /datasources — accept either a flat
      // ``id`` or a wrapped ``featureDataSource.id`` so a future API tweak
      // doesn't silently break the chip again.
      const newId =
        res.data?.id ||
        res.data?.featureDataSource?.id ||
        res.data?.dataSource?.id ||
        '';
      workspace.refreshFeatureDataSources();
      if (newId) {
        setPendingAttachFdsId(newId);
      }
    } catch (err) {
      console.error('Failed to add feature source to chat:', err);
    }
  }, [instanceId, workspace]);

  const [pendingAttachDsId, setPendingAttachDsId] = useState<string>('');
  const _handleAttachDataSource = useCallback((dsId: string) => {
    setPendingAttachDsId(dsId);
  }, []);

  const _handleDataSourceDrop = useCallback(async (params: { connectionId: string; sourceType: string; path: string; label: string; displayPath?: string }) => {
    try {
      const res = await api.post(`/api/workspace/${instanceId}/datasources`, {
        connectionId: params.connectionId,
        sourceType: params.sourceType,
        path: params.path,
        label: params.label,
        displayPath: params.displayPath || params.label,
      });
      const newId = res.data?.id || res.data?.dataSource?.id;
      if (newId) {
        setPendingAttachDsId(newId);
        workspace.refreshDataSources();
      }
    } catch (err) {
      console.error('Failed to drop data source to chat:', err);
    }
  }, [instanceId, workspace]);

  const _leftPanelBody = (
    <UnifiedDataBar
      context={_udbContext}
      activeTab={udbTab}
      onTabChange={setUdbTab}
      onSelectChat={_handleConversationSelect}
      activeWorkflowId={workspace.workflowId ?? undefined}
      onCreateNewChat={workspace.resetToNew}
      onRenameChat={_handleRenameChat}
      onDeleteChat={_handleDeleteChat}
      onFileSelect={_handleFileSelect}
      onSourcesChanged={_handleSourcesChanged}
      onSendToChat_Files={_handleSendToChat_Files}
      onSendToChat_FeatureSource={_handleSendToChat_FeatureSource}
      onAttachDataSource={_handleAttachDataSource}
    />
  );

  const _rightPanelBody = (
    <>
      <div style={{ padding: '6px 12px', borderBottom: '1px solid var(--border-color, #e0e0e0)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', gap: 8 }}>
          <button style={tabButtonStyle(rightTab === 'activity')} onClick={() => setRightTab('activity')}>{t('Aktivität')}</button>
          <button style={tabButtonStyle(rightTab === 'preview')} onClick={() => setRightTab('preview')}>{t('Vorschau')}</button>
        </div>
        {!isMobile && (
          <button onClick={() => setRightCollapsed(true)} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 14, color: '#888' }}>▶</button>
        )}
      </div>
      <div style={{ flex: 1, overflow: 'auto' }}>
        {rightTab === 'activity' && (
          <ToolActivityLog activities={workspace.toolActivities} />
        )}
        {rightTab === 'preview' && (
          <FilePreview
            instanceId={instanceId}
            fileId={selectedFileId}
            files={workspace.files}
          />
        )}
      </div>
    </>
  );

  return (
    <div style={{ display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden', position: 'relative' }}>
      {/* Left sidebar */}
      {!isMobile && !leftCollapsed && (
        <aside style={{
          width: _leftResize.width,
          minWidth: 200,
          borderRight: '1px solid var(--border-color, #e0e0e0)',
          display: 'flex',
          flexDirection: 'column',
          overflow: 'hidden',
          flexShrink: 0,
        }}>
          <div style={{ padding: '6px 12px', borderBottom: '1px solid var(--border-color, #e0e0e0)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span style={{ fontWeight: 600, fontSize: 14 }}>{t('Workspace')}</span>
            <button onClick={() => setLeftCollapsed(true)} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 14, color: '#888' }}>◀</button>
          </div>
          {_leftPanelBody}
        </aside>
      )}

      {/* Left resize handle */}
      {!isMobile && !leftCollapsed && (
        <div
          onMouseDown={e => _leftResize.onMouseDown(e, 1)}
          style={{ width: 4, cursor: 'col-resize', background: 'transparent', flexShrink: 0 }}
          onMouseEnter={e => (e.currentTarget.style.background = 'var(--primary-color, #F25843)')}
          onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}
        />
      )}

      {!isMobile && leftCollapsed && (
        <div style={{ width: 32, display: 'flex', alignItems: 'start', justifyContent: 'center', paddingTop: 8, borderRight: '1px solid var(--border-color, #e0e0e0)' }}>
          <button onClick={() => setLeftCollapsed(false)} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 14, color: '#888' }}>▶</button>
        </div>
      )}

      {/* Hidden file input */}
      <input ref={fileInputRef} type="file" multiple style={{ display: 'none' }} onChange={_handleFileInputChange} />

      {/* Center - Chat + Input */}
      <main
        style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minWidth: 0, minHeight: 0, position: 'relative' }}
        onDragEnter={_handleDragEnter}
        onDragLeave={_handleDragLeave}
        onDragOver={_handleDragOver}
        onDrop={_handleDrop}
      >
        {isMobile && (
          <div style={{
            display: 'flex',
            gap: 8,
            padding: '8px 12px',
            borderBottom: '1px solid var(--border-color, #e0e0e0)',
            background: 'var(--bg-primary, #fff)',
            flexWrap: 'wrap',
          }}>
            <button
              onClick={() => setMobileLeftOpen(true)}
              style={{
                padding: '6px 10px',
                borderRadius: 8,
                border: '1px solid var(--border-color, #ddd)',
                background: '#f7f7f7',
                cursor: 'pointer',
                fontSize: 12,
                fontWeight: 600,
              }}
            >
              {t('Workspace')}
            </button>
            <button
              onClick={() => { setRightTab('activity'); setMobileRightOpen(true); }}
              style={{
                padding: '6px 10px',
                borderRadius: 8,
                border: '1px solid var(--border-color, #ddd)',
                background: rightTab === 'activity' ? 'var(--primary-dark-bg, rgba(242, 88, 67, 0.1))' : '#f7f7f7',
                cursor: 'pointer',
                fontSize: 12,
              }}
            >
              {t('Aktivität')}
            </button>
            <button
              onClick={() => { setRightTab('preview'); setMobileRightOpen(true); }}
              style={{
                padding: '6px 10px',
                borderRadius: 8,
                border: '1px solid var(--border-color, #ddd)',
                background: rightTab === 'preview' ? 'var(--primary-dark-bg, rgba(242, 88, 67, 0.1))' : '#f7f7f7',
                cursor: 'pointer',
                fontSize: 12,
              }}
            >
              {t('Vorschau')}
            </button>
          </div>
        )}
        {isDragOver && (
          <div style={{
            position: 'absolute', inset: 0, zIndex: 100,
            background: 'var(--primary-dark-bg, rgba(242, 88, 67, 0.1))',
            border: '2px dashed var(--primary-color, #F25843)', borderRadius: 8,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontSize: 16, fontWeight: 600, color: 'var(--primary-color, #F25843)',
            pointerEvents: 'none',
          }}>
            Dateien hier ablegen
          </div>
        )}
        <ChatStream
          messages={workspace.messages}
          agentProgress={workspace.agentProgress}
          isProcessing={workspace.isProcessing}
          pendingEdits={workspace.pendingEdits}
          onAcceptEdit={workspace.acceptEdit}
          onRejectEdit={workspace.rejectEdit}
          onOpenEditor={() => navigate(`/mandates/${mandateId}/${featureCode}/${routeInstanceId}/editor`)}
        />
        <WorkspaceInput
          instanceId={instanceId}
          onSend={(prompt, fileIds, dataSourceIds, featureDataSourceIds, options) => {
            const allFileIds = [...new Set([...pendingFiles.map(f => f.fileId), ...(fileIds || [])])];
            const resolvedProviders = _toBackendProviders(providerSelection, allowedProviders);
            workspace.sendMessage(prompt, allFileIds, dataSourceIds, resolvedProviders, featureDataSourceIds, options);
            setPendingFiles([]);
          }}
          isProcessing={workspace.isProcessing}
          onStop={workspace.stopProcessing}
          files={workspace.files}
          dataSources={workspace.dataSources}
          featureDataSources={workspace.featureDataSources}
          pendingFiles={pendingFiles}
          onRemovePendingFile={_handleRemovePendingFile}
          onFileUploadClick={() => fileInputRef.current?.click()}
          uploading={fileOps.uploadingFile}
          providerSelection={providerSelection}
          onProviderSelectionChange={setProviderSelection}
          isMobile={isMobile}
          onTreeItemsDrop={_handleTreeItemsDrop}
          onFeatureSourceDrop={_handleSendToChat_FeatureSource}
          onDataSourceDrop={_handleDataSourceDrop}
          pendingAttachDsId={pendingAttachDsId}
          onPendingAttachDsConsumed={() => setPendingAttachDsId('')}
          pendingAttachFdsId={pendingAttachFdsId}
          onPendingAttachFdsConsumed={() => setPendingAttachFdsId('')}
          onPasteAsFile={_uploadAndAttach}
          draftAppend={draftAppend}
          onDraftAppendConsumed={() => setDraftAppend('')}
        />
      </main>

      {/* Right resize handle */}
      {!isMobile && !rightCollapsed && (
        <div
          onMouseDown={e => _rightResize.onMouseDown(e, -1)}
          style={{ width: 4, cursor: 'col-resize', background: 'transparent', flexShrink: 0 }}
          onMouseEnter={e => (e.currentTarget.style.background = 'var(--primary-color, #F25843)')}
          onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}
        />
      )}

      {/* Right sidebar */}
      {!isMobile && !rightCollapsed && (
        <aside style={{
          width: _rightResize.width,
          minWidth: 200,
          borderLeft: '1px solid var(--border-color, #e0e0e0)',
          display: 'flex',
          flexDirection: 'column',
          overflow: 'hidden',
          flexShrink: 0,
        }}>
          {_rightPanelBody}
        </aside>
      )}

      {!isMobile && rightCollapsed && (
        <div style={{ width: 32, display: 'flex', alignItems: 'start', justifyContent: 'center', paddingTop: 8, borderLeft: '1px solid var(--border-color, #e0e0e0)' }}>
          <button onClick={() => setRightCollapsed(false)} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 14, color: '#888' }}>◀</button>
        </div>
      )}

      {isMobile && mobileLeftOpen && (
        <div
          style={{
            position: 'absolute',
            inset: 0,
            background: 'rgba(0, 0, 0, 0.35)',
            zIndex: 120,
            display: 'flex',
          }}
          onClick={() => setMobileLeftOpen(false)}
        >
          <aside
            style={{
              width: '100%',
              maxWidth: 460,
              height: '100%',
              background: 'var(--bg-primary, #fff)',
              borderRight: '1px solid var(--border-color, #e0e0e0)',
              display: 'flex',
              flexDirection: 'column',
              overflow: 'hidden',
            }}
            onClick={e => e.stopPropagation()}
          >
            <div style={{ padding: '10px 12px', borderBottom: '1px solid var(--border-color, #e0e0e0)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <span style={{ fontWeight: 600, fontSize: 14 }}>{t('Workspace')}</span>
              <button onClick={() => setMobileLeftOpen(false)} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 18, color: '#666' }}>×</button>
            </div>
            {_leftPanelBody}
          </aside>
        </div>
      )}

      {isMobile && mobileRightOpen && (
        <div
          style={{
            position: 'absolute',
            inset: 0,
            background: 'rgba(0, 0, 0, 0.35)',
            zIndex: 120,
            display: 'flex',
            justifyContent: 'flex-end',
          }}
          onClick={() => setMobileRightOpen(false)}
        >
          <aside
            style={{
              width: '100%',
              maxWidth: 460,
              height: '100%',
              background: 'var(--bg-primary, #fff)',
              borderLeft: '1px solid var(--border-color, #e0e0e0)',
              display: 'flex',
              flexDirection: 'column',
              overflow: 'hidden',
            }}
            onClick={e => e.stopPropagation()}
          >
            <div style={{ padding: '10px 12px', borderBottom: '1px solid var(--border-color, #e0e0e0)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <span style={{ fontWeight: 600, fontSize: 14 }}>{rightTab === 'activity' ? t('Aktivität') : t('Vorschau')}</span>
              <button onClick={() => setMobileRightOpen(false)} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 18, color: '#666' }}>×</button>
            </div>
            {_rightPanelBody}
          </aside>
        </div>
      )}
    </div>
  );
};

export default WorkspacePage;
