import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import Logs from "../components/Logs"
import Toast from "../components/Toast";
import axios from "axios";
import {
  Typography,
  Container,
  Button,
  Paper,
  Box,
  useTheme,
} from "@mui/material";
import {
  CloudUpload as CloudUploadIcon,
  VolumeUp as VolumeUpIcon,
} from "@mui/icons-material";
import StepperComponent from "../components/StepperComponent";
import { useWebSocket } from "../contexts/WebSocketContext";
import { useMediaContext } from "../contexts/MediaContext";
import { formatLogMessage } from "../utils/logUtils";

function UploadPage() {
  const navigate = useNavigate();
  const theme = useTheme();
  const { socket, isConnected } = useWebSocket();
  const { setMediaFile, setResponse, setLogs, setToastOpen, setToastMessage } = useMediaContext();
  const [file, setFile] = useState<File | null>(null);
  const [isDragging, setIsDragging] = useState(false);
  const [upload, setUpload] = useState(false);
  const [inputEnabled, setInputEnabled] = useState(false);

  const showErrorToast = (message: string) => {
    setToastMessage(message);
    setToastOpen(true);
  }

  useEffect(() => {
    const startLogs = async () => {
      setLogs([formatLogMessage("Initializing freqsplit")]);
  
      setLogs((prevLogs) => [
        ...prevLogs,
        formatLogMessage("Connecting to server"),
      ]);
  
      axios
        .get("/api/ping")
        .then((ping_resp) => {
          if (ping_resp.status === 200) {
            setLogs((prevLogs) => [
              ...prevLogs,
              formatLogMessage("Connection established successfully"),
            ]);
            setLogs((prevLogs) => [
              ...prevLogs,
              formatLogMessage("Waiting for WebSocket connection"),
            ]);
  
            const checkWebSocketConnection = () => {
              if (isConnected) {
                setLogs((prevLogs) => [
                  ...prevLogs,
                  formatLogMessage("WebSocket connected"),
                ]);
                setInputEnabled(true);
              } else {
                setTimeout(checkWebSocketConnection, 100);
              }
            };
  
            checkWebSocketConnection();
          } else {
            setLogs((prevLogs) => [
              ...prevLogs,
              formatLogMessage("Failed to connect to server"),
            ]);
          }
        })
        .catch(() => {
          setLogs((prevLogs) => [
            ...prevLogs,
            formatLogMessage("Failed to connect to server"),
          ]);
        });
    };
  
    startLogs();
  }, [isConnected]);
 
  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDragging(true);
  };

  const handleDragLeave = () => {
    setIsDragging(false);
  };

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDragging(false);

    const droppedFile = e.dataTransfer.files[0];
    validateAndSetFile(droppedFile);
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setUpload(false);
    setResponse({
      audio_class: "",
      file_uuid: "",
      sr: 0,
      spectrogram: "",
      spec_sr: 0
    });
    const selectedFile = e.target.files?.[0] || null;
    const maxSize = 100 * 1024 * 1024; // 100MB in bytes
    
    if (selectedFile) {
      if (selectedFile.size > maxSize) {
        showErrorToast("Max file size is 100MB!");
        setFile(null);
        setUpload(false);
        e.target.value = "";
        return;
      }
    }

    validateAndSetFile(selectedFile);
    handleUpload(selectedFile);
  };

  const validateAndSetFile = (file: File | null) => {
    if (!file) return;

    const fileType = file.type;
    if (!fileType.includes("audio") && !fileType.includes("video")) {
      showErrorToast("Please upload only audio or video files.");
      return;
    }

    setFile(file);
  };

  const handleContinue = () => {
    if (file) {
      
      setMediaFile({
        name: file.name,
        url: URL.createObjectURL(file),
        type: file.type,
      }); //
      navigate('/preview');
    } else {
      showErrorToast("Please upload a file to continue");
    }
  };

  const handleUpload = async (file: File | null) => {
    if (!file) {
      console.error("No file selected!");
      return; // Exit early if file is null
    }
  
    const formData = new FormData();
    formData.append("file", file);
  
    try {
      setLogs((prevLogs) => [...prevLogs, formatLogMessage("freqsplit/input: Uploading audio file")]);
      const res = await axios.post<{
        file_uuid: string;
        sr: number;
        audio_class: string;
        spectrogram: string;
        spec_sr: number;
      }>("/api/upload", formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      });
  
      if (res.status === 201 && res.data) {
        setResponse( ({
          audio_class: res.data.audio_class,
          file_uuid: res.data.file_uuid,
          sr: res.data.sr,
          spectrogram: res.data.spectrogram,
          spec_sr: res.data.spec_sr
        }));
        if (socket && isConnected){
          socket.send(JSON.stringify({ file_uuid: res.data.file_uuid }))
        } else {
          console.error("Websocket not connected!");
        }
        
        setUpload(true);
        setLogs((prevLogs) => [...prevLogs, formatLogMessage(`freqsplit/input: Uploaded file successfully`)])
        setLogs((prevLogs) => [...prevLogs, formatLogMessage(`freqsplit/input: file_uuid: ${res.data.file_uuid}`)])
        setLogs((prevLogs) => [...prevLogs, formatLogMessage(`freqsplit/input: audio_class: ${res.data.audio_class}`)])
      }
    } catch (error) {
      showErrorToast("Failed to upload file");
      setUpload(false);
      setResponse({
        audio_class: "",
        file_uuid: "",
        sr: 0,
        spectrogram: "",
        spec_sr: 0
      });
      setFile(null);
      console.error("Upload failed:", error);
    }
  };
  
  return (
    <Container maxWidth="md" sx={{ py: 4 }}>
      <StepperComponent activeStep={0} />

      <Paper elevation={3} sx={{ p: 4, mt: 4, textAlign: "center" }}>
        <Typography variant="h4" gutterBottom color="primary">
          Upload Your Media
        </Typography>

        <Box
          sx={{
            border: `2px dashed ${
              isDragging ? theme.palette.primary.main : theme.palette.divider
            }`,
            borderRadius: 2,
            p: 6,
            mt: 3,
            mb: 3,
            backgroundColor: isDragging
              ? "rgba(63, 81, 181, 0.08)"
              : "transparent",
            transition: "all 0.3s ease",
            cursor: "pointer",
            overflow: "auto"
          }}
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onDrop={handleDrop}
          onClick={() => document.getElementById("fileInput")?.click()}
        >
          <input
            type="file"
            id="fileInput"
            style={{ display: "none" }}
            onChange={handleFileChange}
            accept="audio/*"
            disabled={!inputEnabled}
          />
          
          <CloudUploadIcon color="primary" sx={{ fontSize: 64, mb: 2 }} />
          <Typography
            variant="h6"
            gutterBottom
            sx={{
              whiteSpace: "nowrap",
              overflow: "hidden",
              textOverflow: "ellipsis",
              maxWidth: "100%", // Ensure it adapts to the box size
            }}
          >
            {file ? file.name : "Drop your file here or click to browse files"}
          </Typography>
          <Typography>
            Max file size: 100MB
          </Typography>
          {file && (
            <Typography variant="body2" color="textSecondary">
              {file.type.includes("audio") ? <VolumeUpIcon sx={{ mr: 1 }} /> : null}
              {file.type} - {(file.size / (1024 * 1024)).toFixed(2)} MB
            </Typography>
          )}
        </Box>

        <Box sx={{ mt: 4, display: "flex", justifyContent: "space-between" }}>
          <Button
            variant="outlined"
            color="primary"
            onClick={() => navigate("/")}
          >
            Back to Home
          </Button>
          <Button
            variant="contained"
            color="primary"
            onClick={handleContinue}
            disabled={!upload}
          >
            Continue to Preview
          </Button>
        </Box>
      </Paper>
      <Logs />
      <Toast />
    </Container>
  );
}

export default UploadPage;
