import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { FaTrash, FaPlay } from 'react-icons/fa';
import { BsDatabaseGear } from 'react-icons/bs';
import { useNavigate } from 'react-router-dom';
import './DashboardPage.css';

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;

const DashboardPage = () => {
  // User, assistant, and file states
  const [currentUser, setCurrentUser] = useState(null);
  const [assistants, setAssistants] = useState([]);
  const [selectedAssistant, setSelectedAssistant] = useState(null);
  const [assignedFiles, setAssignedFiles] = useState([]);
  const [files, setFiles] = useState([]);

  // Selection states
  const [selectedFiles, setSelectedFiles] = useState([]);
  const [selectedAssistantFiles, setSelectedAssistantFiles] = useState([]);

  // Other states
  const [fileContent, setFileContent] = useState('');
  const [newAssistantName, setNewAssistantName] = useState('');
  const [uploadFiles, setUploadFiles] = useState([]);
  const [loadingEmbeddings, setLoadingEmbeddings] = useState(null);
  
  // State for the filename wildcard filter
  const [filenameFilter, setFilenameFilter] = useState('');

  const navigate = useNavigate();
  const authHeader = { Authorization: `Bearer ${localStorage.getItem('token')}` };

  // Initial data fetches
  useEffect(() => {
    fetchCurrentUser();
    fetchAssistants();
    fetchFiles();
  }, []);

  // Auto-select the first assistant when assistants list updates
  useEffect(() => {
    if (assistants.length > 0 && (!selectedAssistant || !assistants.some(a => a.id === selectedAssistant))) {
      fetchAssignedFiles(assistants[0].id);
    }
  }, [assistants]);

  const fetchCurrentUser = async () => {
    try {
      const res = await axios.get(`${API_BASE_URL}/api/users/me`, { headers: authHeader });
      setCurrentUser(res.data);
    } catch (error) {
      console.error('Error fetching current user:', error);
    }
  };

  const fetchAssistants = async () => {
    try {
      const res = await axios.get(`${API_BASE_URL}/api/assistants`, { headers: authHeader });
      setAssistants(res.data);
    } catch (error) {
      console.error('Error fetching assistants:', error);
    }
  };

  const fetchFiles = async () => {
    try {
      const res = await axios.get(`${API_BASE_URL}/api/files`, { headers: authHeader });
      setFiles(res.data);
    } catch (error) {
      console.error('Error fetching files:', error);
    }
  };

  const fetchAssignedFiles = async (assistantId) => {
    try {
      const res = await axios.get(`${API_BASE_URL}/api/assistants/${assistantId}/files`, { headers: authHeader });
      setAssignedFiles(res.data);
      setSelectedAssistant(assistantId);
      setSelectedAssistantFiles([]);
    } catch (error) {
      console.error('Error fetching assigned files:', error);
      setAssignedFiles([]);
      setSelectedAssistant(assistantId);
      setSelectedAssistantFiles([]);
    }
  };

  const handleCreateAssistant = async () => {
    if (!newAssistantName) return alert('Please enter an assistant name');
    try {
      await axios.post(`${API_BASE_URL}/api/assistants`, { assistant_name: newAssistantName }, { headers: authHeader });
      setNewAssistantName('');
      fetchAssistants();
    } catch (error) {
      console.error('Error creating assistant:', error);
    }
  };

  const handleDeleteAssistant = async (assistantId) => {
    if (!window.confirm('Are you sure you want to delete this assistant?')) return;
    try {
      await axios.delete(`${API_BASE_URL}/api/assistants/${assistantId}`, { headers: authHeader });
      if (selectedAssistant === assistantId) {
        setAssignedFiles([]);
        setSelectedAssistant(null);
      }
      fetchAssistants();
    } catch (error) {
      console.error('Error deleting assistant:', error);
    }
  };

  const executeAssistant = (assistantId) => {
    navigate(`/query/${assistantId}`);
  };

  const handleGenerateEmbeddings = async (assistantId) => {
    setLoadingEmbeddings(assistantId);
    try {
      await axios.post(`${API_BASE_URL}/api/assistants/${assistantId}/embeddings`, {}, { headers: authHeader });
      alert('Embeddings generation triggered successfully');
      fetchAssistants();
    } catch (error) {
      console.error('Error generating embeddings:', error);
      alert('Error generating embeddings');
    } finally {
      setLoadingEmbeddings(null);
    }
  };

  const handleAssignFiles = async (assistantId) => {
    if (selectedFiles.length === 0) return alert('Please select files to assign');
    try {
      await axios.post(`${API_BASE_URL}/api/assistants/${assistantId}/files`, { fileIds: selectedFiles }, { headers: authHeader });
      setSelectedFiles([]);
      fetchAssignedFiles(assistantId);
    } catch (error) {
      console.error('Error assigning files:', error);
    }
  };

  const handleUnassignFile = async (assistantId, fileId) => {
    try {
      await axios.delete(`${API_BASE_URL}/api/assistants/${assistantId}/files/${fileId}`, { headers: authHeader });
      fetchAssignedFiles(assistantId);
    } catch (error) {
      console.error('Error unassigning file:', error);
    }
  };

  const handleUnassignMultipleAssistantFiles = async () => {
    if (selectedAssistantFiles.length === 0) return;
    if (!window.confirm('Are you sure you want to remove the selected files?')) return;
    try {
      const fileIdsToUnassign = [...selectedAssistantFiles];
      await Promise.all(
        fileIdsToUnassign.map(fileId =>
          axios.delete(`${API_BASE_URL}/api/assistants/${selectedAssistant}/files/${fileId}`, { headers: authHeader })
        )
      );
      setSelectedAssistantFiles([]);
      fetchAssignedFiles(selectedAssistant);
    } catch (error) {
      console.error('Error unassigning multiple files:', error);
    }
  };

  const handleFileUpload = async () => {
    if (!uploadFiles || uploadFiles.length === 0) return alert('Please select at least one file to upload');
    const formData = new FormData();
    for (let file of uploadFiles) {
      formData.append('files', file);
    }
    try {
      await axios.post(`${API_BASE_URL}/api/files/upload`, formData, { headers: authHeader });
      setUploadFiles([]);
      fetchFiles();
    } catch (error) {
      console.error('Error uploading files:', error);
    }
  };

  const handleDeleteFile = async (fileId) => {
    if (!window.confirm('Are you sure you want to delete this file?')) return;
    try {
      await axios.delete(`${API_BASE_URL}/api/files/${fileId}`, { headers: authHeader });
      fetchFiles();
      if (selectedAssistant) fetchAssignedFiles(selectedAssistant);
    } catch (error) {
      console.error('Error deleting file:', error);
    }
  };

  const handleDeleteMultipleFiles = async () => {
    if (selectedFiles.length === 0) return;
    if (!window.confirm('Are you sure you want to delete the selected files?')) return;
    try {
      await Promise.all(
        selectedFiles.map((fileId) =>
          axios.delete(`${API_BASE_URL}/api/files/${fileId}`, { headers: authHeader })
        )
      );
      setSelectedFiles([]);
      fetchFiles();
      if (selectedAssistant) {
        fetchAssignedFiles(selectedAssistant);
      }
    } catch (error) {
      console.error('Error deleting multiple files:', error);
    }
  };

  const handleFileSelect = (fileId) => {
    setSelectedFiles((prev) =>
      prev.includes(fileId) ? prev.filter(id => id !== fileId) : [...prev, fileId]
    );
  };

  const handleAssistantFileSelect = (fileId) => {
    setSelectedAssistantFiles((prev) =>
      prev.includes(fileId) ? prev.filter(id => id !== fileId) : [...prev, fileId]
    );
  };

  const handleSelectAllFiles = (e) => {
    if (e.target.checked) {
      setSelectedFiles(files.map(file => file.id));
    } else {
      setSelectedFiles([]);
    }
  };

  const handleSelectAllAssistantFiles = (e) => {
    if (e.target.checked) {
      setSelectedAssistantFiles(assignedFiles.map(file => file.id));
    } else {
      setSelectedAssistantFiles([]);
    }
  };

  // New function to check all files matching the wildcard input.
  const handleCheckMatchingFiles = () => {
    const filter = filenameFilter.trim().toLowerCase();
    if (!filter) return;
    const matchingFileIds = files
      .filter(file => file.file_name.toLowerCase().includes(filter))
      .map(file => file.id);
    // Merge matching file IDs with the already selected files.
    setSelectedFiles(prev => Array.from(new Set([...prev, ...matchingFileIds])));
  };

  const handlePreviewFile = async (filePath) => {
    try {
      const filename = filePath.split('/').pop();
      const res = await axios.get(`${API_BASE_URL}/api/files/preview/${filename}`, {
        responseType: 'blob',
        headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
      });
      const reader = new FileReader();
      reader.onload = () => setFileContent(reader.result);
      reader.readAsText(res.data);
    } catch (error) {
      console.error('Error fetching file content:', error);
      setFileContent('Unable to preview file.');
    }
  };

  return (
    <div className="container-fluid p-4">
      {/* Top Section: Welcome Message */}
      <div className="row mb-4">
        <div className="col-12">
          <h2>{currentUser ? `Welcome, ${currentUser.first_name}!` : 'Welcome!'}</h2>
        </div>
      </div>
      {/* Three-Column Layout */}
      <div className="row">
        {/* Left Column: AI Assistants */}
        <div className="col-md-3">
          <h4>Your AI Assistants</h4>
          <ul className="list-group mb-2">
            {assistants.map((assistant) => (
              <li
                key={assistant.id}
                className={`list-group-item d-flex justify-content-between align-items-center ${assistant.id === selectedAssistant ? 'active' : ''}`}
              >
                <span style={{ cursor: 'pointer' }} onClick={() => fetchAssignedFiles(assistant.id)}>
                  {assistant.assistant_name}
                </span>
                <div>
                  <FaPlay style={{ cursor: 'pointer', marginRight: '10px' }} onClick={() => executeAssistant(assistant.id)} />
                  <BsDatabaseGear
                    className={loadingEmbeddings === assistant.id ? 'spin' : ''}
                    style={{ cursor: 'pointer', marginRight: '10px' }}
                    onClick={() => handleGenerateEmbeddings(assistant.id)}
                  />
                  <FaTrash style={{ cursor: 'pointer' }} onClick={() => handleDeleteAssistant(assistant.id)} />
                </div>
              </li>
            ))}
          </ul>
          <div className="mt-2">
            <input
              type="text"
              value={newAssistantName}
              onChange={(e) => setNewAssistantName(e.target.value)}
              placeholder="New Assistant Name"
              className="form-control"
            />
            <button className="btn btn-primary mt-2" onClick={handleCreateAssistant}>
              Add Assistant
            </button>
          </div>
        </div>
        {/* Middle Column: Assistant Files */}
        <div className="col-md-4">
          <h4>Assistant Files</h4>
          {selectedAssistant ? (
            <>
              {assignedFiles.length > 0 ? (
                <>
                  <div className="d-flex align-items-center mb-2">
                    <input
                      type="checkbox"
                      className="me-2"
                      onChange={handleSelectAllAssistantFiles}
                      checked={assignedFiles.length > 0 && selectedAssistantFiles.length === assignedFiles.length}
                    />
                    <span>Select All/None</span>
                  </div>
                  <ul className="list-group mb-2">
                    {assignedFiles.map((file) => (
                      <li key={file.id} className="list-group-item d-flex justify-content-between align-items-center">
                        <div>
                          <input
                            type="checkbox"
                            className="me-2"
                            checked={selectedAssistantFiles.includes(file.id)}
                            onChange={() => handleAssistantFileSelect(file.id)}
                          />
                          <span style={{ cursor: 'pointer' }} onClick={() => handlePreviewFile(file.file_path)}>
                            {file.file_name}
                          </span>
                        </div>
                        <FaTrash style={{ cursor: 'pointer' }} onClick={() => handleUnassignFile(selectedAssistant, file.id)} />
                      </li>
                    ))}
                  </ul>
                  {selectedAssistantFiles.length > 0 && (
                    <button className="btn btn-secondary w-100" onClick={handleUnassignMultipleAssistantFiles}>
                      Delete Selected Assistant Files
                    </button>
                  )}
                </>
              ) : (
                <p>No files assigned yet.</p>
              )}
              <button className="btn btn-secondary w-100" onClick={() => handleAssignFiles(selectedAssistant)}>
                Assign Selected Files
              </button>
            </>
          ) : (
            <p>Please select an assistant to view its files.</p>
          )}
        </div>
        {/* Right Column: Library */}
        <div className="col-md-5">
          <h4>Library of your files</h4>
          <div className="mb-3">
            <input
              type="file"
              multiple
              className="form-control"
              onChange={(e) => {
                console.log('Files selected:', e.target.files);
                setUploadFiles(e.target.files);
              }}
            />
            <button className="btn btn-success mt-2" onClick={handleFileUpload}>
              Upload Files
            </button>
          </div>
          <div className="d-flex align-items-center mb-2">
            <input
              type="checkbox"
              className="me-2"
              onChange={handleSelectAllFiles}
              checked={files.length > 0 && selectedFiles.length === files.length}
            />
            <span>Select All/None</span>
            {/* Wildcard filter textbox and button */}
            <input
              type="text"
              className="form-control ms-2"
              placeholder="Wildcard filter"
              value={filenameFilter}
              onChange={(e) => setFilenameFilter(e.target.value)}
              style={{ maxWidth: '200px' }}
            />
            <button className="btn btn-secondary ms-2" onClick={handleCheckMatchingFiles}>
              Check all matching files
            </button>
          </div>
          <ul className="list-group mb-2">
            {files.map((file) => (
              <li key={file.id} className="list-group-item d-flex justify-content-between align-items-center">
                <div>
                  <input
                    type="checkbox"
                    checked={selectedFiles.includes(file.id)}
                    onChange={() => handleFileSelect(file.id)}
                    className="me-2"
                  />
                  <span style={{ cursor: 'pointer' }} onClick={() => handlePreviewFile(file.file_path)}>
                    {file.file_name}
                  </span>
                </div>
                <FaTrash style={{ cursor: 'pointer' }} onClick={() => handleDeleteFile(file.id)} />
              </li>
            ))}
          </ul>
          {selectedFiles.length > 0 && (
            <button className="btn btn-danger w-100" onClick={handleDeleteMultipleFiles}>
              Delete Selected Files
            </button>
          )}
          <textarea
            className="form-control"
            rows="10"
            value={fileContent}
            readOnly
            placeholder="Select a file to preview its content"
          ></textarea>
        </div>
      </div>
    </div>
  );
};

export default DashboardPage;

