"use client";

import { useEffect, useState, type ChangeEvent, type DragEvent } from "react";

import CloudUploadOutlinedIcon from "@mui/icons-material/CloudUploadOutlined";
import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import Dialog from "@mui/material/Dialog";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";

import { AppButton } from "@/components/ui/button";
import { getFormBorderColor, getFormSoftBg } from "@/components/ui/form";
import { PdfIcon } from "@/components/ui/icon";

export type UploadDraftSemesterDialogLabels = {
  title: string;
  documentLabel: string;
  uploadText: string;
  uploadHint: string;
  fileTypeHint: string;
  uploading: string;
  completed: string;
  upload: string;
  required: string;
  invalidFileType: string;
  invalidFileSize: string;
  submitError: string;
};

type UploadDraftSemesterDialogProps = {
  open: boolean;
  labels: UploadDraftSemesterDialogLabels;
  onClose: () => void;
  onUpload?: (file: File) => Promise<void>;
};

const DIALOG_WIDTH = 416;
const DIALOG_HEIGHT = 559;
const CONTENT_WIDTH = 360;
const FILE_CARD_WIDTH = 261;
const REUPLOAD_BOX_WIDTH = 77;
const UPLOAD_ROW_HEIGHT = 62;
const HEADER_HEIGHT = 67;
const FOOTER_HEIGHT = 75;
const MAX_PDF_SIZE = 10 * 1024 * 1024;
const UPLOAD_PROGRESS_MS = 1200;

function formatFileSize(size: number) {
  if (size < 1024 * 1024) {
    return `${Math.max(1, Math.round(size / 1024))} KB`;
  }

  return `${(size / (1024 * 1024)).toFixed(1)} MB`;
}

function getDisplayFileName(file: File) {
  const baseName = file.name.replace(/\.pdf$/i, "");
  return baseName || "Draft Semester";
}

function RequiredFieldLabel({ children }: { children: string }) {
  return (
    <Typography
      sx={{
        mb: 1.5,
        fontSize: 13,
        fontWeight: 500,
        color: "text.secondary",
        lineHeight: 1,
      }}
    >
      {children}
      <Typography component="span" sx={{ color: "error.main" }}>
        {" "}
        *
      </Typography>
    </Typography>
  );
}

export function UploadDraftSemesterDialog({
  open,
  labels,
  onClose,
  onUpload,
}: UploadDraftSemesterDialogProps) {
  const theme = useTheme();
  const [file, setFile] = useState<File | null>(null);
  const [error, setError] = useState<string | undefined>();
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploadCompleted, setUploadCompleted] = useState(false);
  const [submitError, setSubmitError] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);

  const hasFile = file !== null;
  const isUploading = hasFile && !uploadCompleted;

  useEffect(() => {
    if (!file) {
      return;
    }

    const startTimer = window.setTimeout(() => setUploadProgress(45), 50);
    const midTimer = window.setTimeout(() => setUploadProgress(78), 600);
    const completeTimer = window.setTimeout(() => {
      setUploadProgress(100);
      setUploadCompleted(true);
    }, UPLOAD_PROGRESS_MS);

    return () => {
      window.clearTimeout(startTimer);
      window.clearTimeout(midTimer);
      window.clearTimeout(completeTimer);
    };
  }, [file]);

  function resetForm() {
    setFile(null);
    setError(undefined);
    setUploadProgress(0);
    setUploadCompleted(false);
    setSubmitError("");
  }

  function closeDialog() {
    if (isSubmitting) return;

    resetForm();
    onClose();
  }

  function selectFile(nextFile?: File) {
    if (!nextFile || isSubmitting) {
      return;
    }

    const isPdf =
      nextFile.type === "application/pdf" ||
      nextFile.name.toLowerCase().endsWith(".pdf");

    if (!isPdf) {
      setFile(null);
      setError(labels.invalidFileType);
      return;
    }

    if (nextFile.size > MAX_PDF_SIZE) {
      setFile(null);
      setError(labels.invalidFileSize);
      return;
    }

    setFile(nextFile);
    setError(undefined);
    setSubmitError("");
    setUploadProgress(0);
    setUploadCompleted(false);
  }

  function handleFileChange(event: ChangeEvent<HTMLInputElement>) {
    selectFile(event.target.files?.[0]);
    event.target.value = "";
  }

  function handleDrop(event: DragEvent<HTMLLabelElement>) {
    event.preventDefault();

    if (isSubmitting) return;

    selectFile(event.dataTransfer.files?.[0]);
  }

  async function handleUpload() {
    if (isSubmitting) return;

    if (!file) {
      setError(labels.required);
      return;
    }

    if (isUploading) {
      return;
    }

    setSubmitError("");
    setIsSubmitting(true);

    try {
      await onUpload?.(file);
      resetForm();
      onClose();
    } catch (requestError) {
      setSubmitError(
        requestError instanceof Error
          ? requestError.message
          : labels.submitError,
      );
    } finally {
      setIsSubmitting(false);
    }
  }

  return (
    <Dialog
      open={open}
      onClose={closeDialog}
      maxWidth={false}
      slotProps={{
        backdrop: {
          sx: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
        },
        paper: {
          sx: {
            width: { xs: "calc(100vw - 32px)", sm: DIALOG_WIDTH },
            height: { xs: "auto", sm: DIALOG_HEIGHT },
            minHeight: { xs: "auto", sm: DIALOG_HEIGHT },
            maxWidth: "calc(100vw - 32px)",
            borderRadius: "16px",
            overflow: "hidden",
            display: "flex",
            flexDirection: "column",
            bgcolor: theme.palette.background.paper,
            color: theme.palette.text.primary,
            boxShadow:
              theme.palette.mode === "dark"
                ? "0 12px 30px rgba(0, 0, 0, 0.5)"
                : "0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03)",
          },
        },
      }}
    >
      <Box
        sx={{
          height: HEADER_HEIGHT,
          px: "22px",
          display: "flex",
          alignItems: "center",
          borderBottom: `1px solid ${
            theme.palette.mode === "dark" ? alpha("#ffffff", 0.12) : "#f5f5f5"
          }`,
          flexShrink: 0,
        }}
      >
        <Typography
          sx={{
            fontSize: 20,
            fontWeight: 500,
            letterSpacing: "-0.4px",
            color: theme.palette.text.primary,
          }}
        >
          {labels.title}
        </Typography>
      </Box>

      <Box
        sx={{
          flex: 1,
          px: { xs: 2, sm: `${(DIALOG_WIDTH - CONTENT_WIDTH) / 2}px` },
          pt: "22px",
          display: "flex",
          flexDirection: "column",
          alignItems: { xs: "stretch", sm: "center" },
        }}
      >
        <Box sx={{ width: "100%", maxWidth: CONTENT_WIDTH }}>
          <RequiredFieldLabel>{labels.documentLabel}</RequiredFieldLabel>

          {file ? (
            <Box
              sx={{
                display: "flex",
                alignItems: "center",
                gap: "22px",
                width: "100%",
                maxWidth: CONTENT_WIDTH,
              }}
            >
              <Box
                sx={{
                  position: "relative",
                  width: FILE_CARD_WIDTH,
                  minWidth: FILE_CARD_WIDTH,
                  height: UPLOAD_ROW_HEIGHT,
                  borderRadius: "6px",
                  bgcolor: getFormSoftBg(theme),
                  overflow: "hidden",
                }}
              >
                <Box
                  sx={{
                    position: "absolute",
                    left: "13px",
                    top: "50%",
                    transform: "translateY(-50%)",
                    display: "flex",
                    alignItems: "center",
                    gap: "12px",
                    maxWidth: 148,
                  }}
                >
                  <PdfIcon sx={{ fontSize: 40, flexShrink: 0 }} />

                  <Box sx={{ minWidth: 0 }}>
                    <Typography
                      noWrap
                      sx={{
                        fontSize: 12,
                        fontWeight: 500,
                        color: "text.primary",
                        lineHeight: 1,
                      }}
                    >
                      {getDisplayFileName(file)}
                    </Typography>
                    <Typography
                      sx={{
                        mt: 1.5,
                        fontSize: 12,
                        lineHeight: 1.24,
                        fontWeight: 400,
                        color: "text.secondary",
                      }}
                    >
                      {formatFileSize(file.size)}
                    </Typography>
                  </Box>
                </Box>

                <Box
                  sx={{
                    position: "absolute",
                    left: "171px",
                    top: "17px",
                    width: 80,
                    display: "flex",
                    flexDirection: "column",
                    alignItems: "center",
                    gap: 1,
                  }}
                >
                  <Typography
                    sx={{
                      fontSize: 11,
                      lineHeight: "16px",
                      fontWeight: 500,
                      color: "text.secondary",
                      textAlign: "center",
                      whiteSpace: "nowrap",
                    }}
                  >
                    {uploadCompleted ? labels.completed : labels.uploading}
                  </Typography>
                  <Box
                    sx={{
                      width: 80,
                      height: 4,
                      borderRadius: "16px",
                      bgcolor: "background.paper",
                      overflow: "hidden",
                    }}
                  >
                    <Box
                      sx={{
                        width: `${uploadProgress}%`,
                        height: "100%",
                        borderRadius: "16px",
                        bgcolor: "#22C55E",
                        transition: "width 0.45s ease",
                      }}
                    />
                  </Box>
                </Box>
              </Box>

              <Box
                component="label"
                onDragOver={(event: DragEvent<HTMLLabelElement>) =>
                  event.preventDefault()
                }
                onDrop={handleDrop}
                sx={{
                  width: REUPLOAD_BOX_WIDTH,
                  minWidth: REUPLOAD_BOX_WIDTH,
                  height: UPLOAD_ROW_HEIGHT,
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  border: `1px dashed ${getFormBorderColor(theme)}`,
                  borderRadius: "12px",
                  bgcolor: getFormSoftBg(theme),
                  cursor: "pointer",
                  flexShrink: 0,
                  transition: "0.2s",
                  "&:hover": {
                    bgcolor: alpha(theme.palette.primary.main, 0.1),
                    borderColor: theme.palette.primary.main,
                  },
                }}
              >
                <CloudUploadOutlinedIcon
                  sx={{ fontSize: 38, color: theme.palette.primary.main }}
                />
                <input
                  hidden
                  type="file"
                  accept="application/pdf,.pdf"
                  disabled={isSubmitting}
                  onChange={handleFileChange}
                />
              </Box>
            </Box>
          ) : (
            <Box
              component="label"
              onDragOver={(event: DragEvent<HTMLLabelElement>) =>
                event.preventDefault()
              }
              onDrop={handleDrop}
              sx={{
                width: "100%",
                maxWidth: CONTENT_WIDTH,
                height: UPLOAD_ROW_HEIGHT,
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                borderRadius: "6px",
                border: `1px dashed ${
                  error ? theme.palette.error.main : getFormBorderColor(theme)
                }`,
                bgcolor: getFormSoftBg(theme),
                cursor: "pointer",
                transition: "0.2s",
                "&:hover": {
                  bgcolor: alpha(theme.palette.primary.main, 0.06),
                  borderColor: theme.palette.primary.main,
                },
              }}
            >
              <Box
                sx={{
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  gap: 1.5,
                }}
              >
                <CloudUploadOutlinedIcon
                  sx={{ fontSize: 38, color: theme.palette.primary.main }}
                />
                <Box>
                  <Box
                    sx={{
                      display: "flex",
                      alignItems: "center",
                      gap: 0.75,
                    }}
                  >
                    <Typography
                      component="span"
                      sx={{
                        fontSize: 12,
                        fontWeight: 600,
                        lineHeight: "18px",
                        color: theme.palette.primary.main,
                      }}
                    >
                      {labels.uploadText}
                    </Typography>
                    <Typography
                      component="span"
                      sx={{
                        fontSize: 12,
                        fontWeight: 600,
                        lineHeight: "18px",
                        color: "text.secondary",
                      }}
                    >
                      {labels.uploadHint}
                    </Typography>
                  </Box>
                  <Typography
                    sx={{
                      fontSize: 11,
                      lineHeight: "16px",
                      color: "text.secondary",
                    }}
                  >
                    {labels.fileTypeHint}
                  </Typography>
                </Box>
              </Box>
              <input
                hidden
                type="file"
                accept="application/pdf,.pdf"
                disabled={isSubmitting}
                onChange={handleFileChange}
              />
            </Box>
          )}

          {error ? (
            <Typography sx={{ mt: 0.5, fontSize: 12, color: "error.main" }}>
              {error}
            </Typography>
          ) : null}

          {submitError ? (
            <Alert severity="error" sx={{ mt: 1 }}>
              {submitError}
            </Alert>
          ) : null}
        </Box>
      </Box>

      <Box
        sx={{
          height: FOOTER_HEIGHT,
          px: "22px",
          display: "flex",
          alignItems: "center",
          justifyContent: "flex-end",
          borderTop: `1px solid ${
            theme.palette.mode === "dark" ? alpha("#ffffff", 0.12) : "#f5f5f5"
          }`,
          flexShrink: 0,
          mt: "auto",
        }}
      >
        <AppButton
          onClick={handleUpload}
          disabled={!hasFile || isUploading || isSubmitting}
          sx={{
            minWidth: 0,
            height: 40,
            minHeight: 40,
            px: "59px",
            py: "12px",
            borderRadius: "6px",
            bgcolor: hasFile ? "#1a64a8" : "#717680",
            fontSize: 13,
            fontWeight: 500,
            lineHeight: 1,
            boxShadow: "none",
            "&:hover": {
              bgcolor: hasFile ? "#155489" : "#5f6773",
              boxShadow: "none",
            },
            "&.Mui-disabled": {
              bgcolor: hasFile ? alpha("#1a64a8", 0.72) : "#717680",
              color: "#ffffff",
            },
          }}
        >
          {labels.upload}
        </AppButton>
      </Box>
    </Dialog>
  );
}
