import ScheduleSendIcon from '@mui/icons-material/ScheduleSend';
import {
  Backdrop, // Import Backdrop component
  Box,
  Button,
  CircularProgress, // Import CircularProgress component
  Container,
  FormControl,
  InputLabel,
  MenuItem,
  Paper,
  Select,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  TextField,
  RadioGroup,
  Radio,
  FormControlLabel,
  FormLabel,
  Alert
} from "@mui/material";
import { styled } from "@mui/material/styles";
import Papa from "papaparse";
import React, { useContext, useState, useCallback } from "react";
import { TopicsContext } from "./UploadFileContext";

const VisuallyHiddenInput = styled("input")({
  clip: "rect(0 0 0 0)",
  clipPath: "inset(50%)",
  height: 1,
  overflow: "hidden",
  position: "absolute",
  bottom: 0,
  left: 0,
  whiteSpace: "nowrap",
  width: 1,
});

function QueryView() {
  const [fileData, setFileData] = useState([]);
  const [selectedColumn, setSelectedColumn] = useState("");
  const [selectedFile, setSelectedFile] = useState(null);
  const [selectedColumnData, setSelectedColumnData] = useState([]);
  const [openSelector, setOpenSelector] = React.useState(false);
  const [xLeftWord, setXLeftWord] = useState("past");
  const [xRightWord, setXRightWord] = useState("future");
  const [yTopWord, setYTopWord] = useState("positive");
  const [yBottomWord, setYBottomWord] = useState("negative");
  const [radiusSize, setRadiusSize] = useState(0.5);
  const [nClusters, setNClusters] = useState(15);
  const [minCountTerms, setMinCountTerms] = useState(1);
  const [nameLength, setNameLength] = useState(3);
  const [cleanTopics, setCleanTopics] = useState(false);
  const [language, setLanguage] = useState("english");
  const { uploadFile, isLoading, selectedView, refreshBourdieuQuery } = useContext(TopicsContext);
  const [fileDataTooLong, setFileDataTooLong] = useState(false);
  const [fileDataError, setFileDataError] = useState(null);

  /**
   * Column name selector handler
   */
  const handleClose = () => {
    setOpenSelector(false);
  };

  const handleOpen = () => {
    setOpenSelector(true);
  };

  /**
   * Parse the CSV and take a sample to display the preview
   * @param {*} file 
   * @param {*} sampleSize 
   * @returns 
   */
  const parseCSVFile = (file, sampleSize = 100) =>
    new Promise((resolve, reject) => {
      const reader = new FileReader();

      reader.onload = (e) => {
        const csvData = e.target.result;
        const lines = csvData.split("\n");

        setFileDataTooLong(lines.length > 10000);
        // Take a sample of the first 500 lines to display preview
        const sampleLines = lines.slice(0, sampleSize).join("\n");

        Papa.parse(sampleLines, {
          complete: (result) => {
            resolve(result.data);
          },
          error: (parseError) => {
            reject(parseError.message);
          },
        });
      };
      reader.readAsText(file);
    });

  /**
   * Handler the file selection ui workflow
   * @param {Event} e 
   * @returns 
   */
  const handleFileChange = async (e) => {
    const file = e.target.files[0];
    setSelectedFile(file);

    if (!file) return;
    // prepare data for the preview Table
    try {
      const parsedData = await parseCSVFile(file);
      setFileData(parsedData);
      setSelectedColumn(""); // Clear the selected column when a new file is uploaded
      if (fileDataTooLong === false) {
        handleOpen();
      }
      else {
        handleClose();
      }
    } catch (exc) {
      setFileDataError("Error parsing the CSV file, please check your file before uploading");
      console.error("Error parsing CSV:", exc);
    }
  };

  const handleColumnSelect = (e) => {
    const columnName = e.target.value;
    setSelectedColumn(columnName);

    // Extract the content of the selected column
    const columnIndex = fileData[0].indexOf(columnName);
    const columnData = fileData.slice(1).map((row) => row[columnIndex]);

    setSelectedColumnData(columnData);
  };

  /**
   * Launch the upload and processing
   */
  const handleProcessTopics = async () => {
    // Return if no column selected
    if (selectedColumnData.length === 0) return;

    if (selectedFile && !isLoading) {
      uploadFile(selectedFile, {
        nClusters,
        selectedColumn,
        selectedView,
        xLeftWord,
        xRightWord,
        yTopWord,
        yBottomWord,
        radiusSize,
        nameLength,
        minCountTerms,
        language,
        cleanTopics
      });
    }
  };

  const handleRefreshQuery = useCallback(async () => {
    if (!isLoading) {
      await refreshBourdieuQuery({
        topic_param: {
          n_clusters: nClusters,
          name_lenght: nameLength,
          min_count_terms: minCountTerms,
          language: language,
          clean_topics: cleanTopics
        },
        bourdieu_query: {
          x_left_words: xLeftWord.split(","),
          x_right_words: xRightWord.split(","),
          y_top_words: yTopWord.split(","),
          y_bottom_words: yBottomWord.split(","),
          radius_size: radiusSize,
        }
      });
    }
  });

  const openTableContainer = selectedColumnData.length > 0 && fileData.length > 0 && fileData.length <= 10000 && fileDataTooLong === false && fileDataError == null;

  return (
    <Container component="form">
      {selectedView === "map" && (
        <>
          <Box marginBottom={2}>
            <Button component="label" variant="outlined" endIcon={<ScheduleSendIcon />}>
              Upload a CSV (max 10 000 lines) and queue processing
              <VisuallyHiddenInput type="file" onChange={handleFileChange} required />
            </Button>
          </Box>
          <Box marginBottom={2}>
            <FormControl variant="outlined" fullWidth>
              <InputLabel>Select a Column</InputLabel>
              <Select value={selectedColumn} onChange={handleColumnSelect} onClose={handleClose} onOpen={handleOpen} open={openSelector}>
                {fileData[0]?.map((header, index) => (
                  <MenuItem key={`${header}`} value={header}>
                    {header}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
          </Box>
        </>
      )}
      {isLoading ? (
        <Backdrop open={isLoading} style={{ zIndex: 9999 }}>
          <CircularProgress color="primary" />
        </Backdrop>
      ) : (
        // Content when not loading
        <div>
          {openTableContainer && (
            <TableContainer component={Paper} style={{ maxHeight: "400px", overflowY: "auto" }}>
              <Table>
                <TableHead>
                  <TableRow>
                    <TableCell>{selectedColumn}</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {selectedColumnData.map((cell, index) => (
                    <TableRow key={`table-${index}`}>
                      <TableCell>{cell}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </TableContainer>
          )}
          {fileDataTooLong && (
            <Alert severity="error">CSV must have less than 10 000 lines (this is a demo)</Alert>
          )}
          {fileDataError && (
            <Alert severity="error">CSV must have less than 10 000 lines (this is a demo)</Alert>
          )}
          {selectedView === "bourdieu" && (
            <Box marginTop={2} display="flex" alignItems="center" flexDirection="column">
              <FormControl variant="outlined">
                <TextField required id="input-bourdieu-xl" sx={{ marginBottom: "0.5em" }} label="X left words (comma separated)" variant="outlined" onChange={e => setXLeftWord(e.target.value)} value={xLeftWord} />
                <TextField required id="input-bourdieu-xr" sx={{ marginBottom: "1em" }} label="X right words (comma separated)" variant="outlined" onChange={e => setXRightWord(e.target.value)} value={xRightWord} />
                <TextField required id="input-bourdieu-yt" sx={{ marginBottom: "1em" }} label="Y top words (comma separated)" variant="outlined" onChange={e => setYTopWord(e.target.value)} value={yTopWord} />
                <TextField required id="input-bourdieu-yb" sx={{ marginBottom: "1em" }} label="Y bottom words (comma separated)" variant="outlined" onChange={e => setYBottomWord(e.target.value)} value={yBottomWord} />
                <TextField required id="input-bourdieu-radius" sx={{ marginBottom: "1em" }} label="Radius Size" variant="outlined" onChange={e => setRadiusSize(e.target.value)} value={radiusSize} />
                <TextField required id="input-map-nclusters" sx={{ marginBottom: "1em" }} label="N° Clusters" variant="outlined" onChange={e => setNClusters(e.target.value)} value={nClusters} />
                <TextField required id="input-map-namelength" sx={{ marginBottom: "1em" }} label="Name length" variant="outlined" onChange={e => setNameLength(e.target.value)} value={nameLength} />
                <TextField required id="input-map-mincountterms" sx={{ marginBottom: "1em" }} label="Min Count Terms" variant="outlined" onChange={e => setMinCountTerms(e.target.value)} value={minCountTerms} />
                <RadioGroup required name="cleantopics-radio-group" defaultValue={cleanTopics} onChange={e => setCleanTopics(e.target.value)} variant="outlined" sx={{ marginBottom: "1em" }} disabled>
                  <FormLabel id="clean-topics-group-label">Clean Topics</FormLabel>
                  <FormControlLabel value={true} label="Yes" control={<Radio />} disabled />
                  <FormControlLabel value={false} label="No" control={<Radio />} disabled />
                </RadioGroup>
              </FormControl>
              <Button variant="contained" color="primary" onClick={handleRefreshQuery} disabled={isLoading || fileDataTooLong === true || fileDataError !== null}>
                {isLoading ? "Processing..." : "Refresh Bourdieu Axes"}
              </Button>
            </Box>
          )}
          {selectedView === "map" && (
            <Box marginTop={2} display="flex" alignItems="center" flexDirection="column">
              <Button variant="contained" color="primary" onClick={handleProcessTopics} disabled={selectedColumnData.length === 0 || isLoading || fileDataTooLong === true || fileDataError !== null}>
                {isLoading ? "Processing..." : "Process Topics"}
              </Button>
              <FormControl variant="outlined" sx={{ marginTop: "1em", marginLeft: "1em" }}>
                <TextField required id="input-map-nclusters" sx={{ marginBottom: "1em" }} label="N° Clusters" variant="outlined" onChange={e => setNClusters(e.target.value)} value={nClusters} />
                <TextField required id="input-map-namelength" sx={{ marginBottom: "1em" }} label="Name length" variant="outlined" onChange={e => setNameLength(e.target.value)} value={nameLength} />
                <TextField required id="input-map-mincountterms" sx={{ marginBottom: "1em" }} label="Min Count Terms" variant="outlined" onChange={e => setMinCountTerms(e.target.value)} value={minCountTerms} />
                <RadioGroup required name="cleantopics-radio-group" defaultValue={cleanTopics} onChange={e => setCleanTopics(e.target.value)} variant="outlined" sx={{ marginBottom: "1em" }} disabled>
                  <FormLabel id="clean-topics-group-label">Clean Topics</FormLabel>
                  <FormControlLabel value={true} label="Yes" control={<Radio />} disabled />
                  <FormControlLabel value={false} label="No" control={<Radio />} disabled />
                </RadioGroup>
                <RadioGroup required name="language-radio-group" defaultValue={language} onChange={e => setLanguage(e.target.value)} variant="outlined" sx={{ marginBottom: "1em" }}>
                  <FormLabel id="language-group-label">Language</FormLabel>
                  <FormControlLabel value="french" label="fr" control={<Radio />} />
                  <FormControlLabel value="english" label="en" control={<Radio />} />
                </RadioGroup>
              </FormControl>
            </Box>
          )}
        </div>
      )}
    </Container>
  );
}

export default QueryView;