"use client";

import { useState } from "react";

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

import { AppButton, AppSecondaryButton } from "@/components/ui/button";
import { getFormBorderColor } from "@/components/ui/form";
import type { UploadedFileMetadata } from "@/lib/document-file";

import { CreateProgressReportDialogFields } from "./create-progress-report-dialog-fields";
import type {
  CreateProgressReportDialogLabels,
  CreateProgressReportFormValues,
  CreateProgressReportSubmitMode,
  ProgressReportFormInitialValues,
} from "./create-progress-report-dialog-types";

type CreateProgressReportDialogProps = {
  open: boolean;
  labels: CreateProgressReportDialogLabels;
  initialValues?: ProgressReportFormInitialValues;
  existingAttachment?: UploadedFileMetadata | null;
  onClose: () => void;
  onSubmit: (
    values: CreateProgressReportFormValues,
    mode: CreateProgressReportSubmitMode,
  ) => Promise<void>;
};

type FormErrors = Partial<
  Record<keyof CreateProgressReportFormValues, string>
>;

const MAX_PDF_SIZE = 20 * 1024 * 1024;

const emptyForm: CreateProgressReportFormValues = {
  title: "",
  semester: "",
  description: "",
  year: "",
  deadline: "",
  attachment: null,
};

function getInitialForm(
  initialValues?: ProgressReportFormInitialValues,
): CreateProgressReportFormValues {
  return {
    ...emptyForm,
    ...initialValues,
    attachment: null,
  };
}

export function CreateProgressReportDialog({
  open,
  labels,
  initialValues,
  existingAttachment,
  onClose,
  onSubmit,
}: CreateProgressReportDialogProps) {
  const theme = useTheme();

  const [values, setValues] = useState<CreateProgressReportFormValues>(() =>
    getInitialForm(initialValues),
  );
  const [errors, setErrors] = useState<FormErrors>({});
  const [submitError, setSubmitError] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);
  const hasStoredAttachment = Boolean(existingAttachment);

  const isFormFilled =
    values.title.trim() !== "" &&
    values.semester !== "" &&
    values.description.trim() !== "" &&
    values.year !== "" &&
    values.deadline !== "" &&
    (values.attachment !== null || hasStoredAttachment);

  function resetForm() {
    setValues(getInitialForm(initialValues));
    setErrors({});
    setSubmitError("");
  }

  function closeDialog() {
    if (isSubmitting) return;

    resetForm();
    onClose();
  }

  function updateValue(
    field: "title" | "semester" | "description" | "year" | "deadline",
    value: string,
  ) {
    setValues((current) => ({ ...current, [field]: value }));
    setErrors((current) => ({ ...current, [field]: undefined }));
  }

  function updateAttachment(file: File | null) {
    if (!file) {
      setValues((current) => ({ ...current, attachment: null }));
      return;
    }

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

    if (!isPdf) {
      setValues((current) => ({ ...current, attachment: null }));
      setErrors((current) => ({
        ...current,
        attachment: labels.invalidFileType,
      }));
      return;
    }

    if (file.size > MAX_PDF_SIZE) {
      setValues((current) => ({ ...current, attachment: null }));
      setErrors((current) => ({
        ...current,
        attachment: labels.invalidFileSize,
      }));
      return;
    }

    setValues((current) => ({ ...current, attachment: file }));
    setErrors((current) => ({ ...current, attachment: undefined }));
  }

  async function handleSubmit(mode: CreateProgressReportSubmitMode) {
    if (isSubmitting) return;

    const nextErrors: FormErrors = {};

    if (!values.title.trim()) nextErrors.title = labels.required;
    if (!values.semester) nextErrors.semester = labels.required;
    if (!values.description.trim()) nextErrors.description = labels.required;
    if (!values.year) nextErrors.year = labels.required;
    if (!values.deadline) nextErrors.deadline = labels.required;
    if (!values.attachment && !hasStoredAttachment) {
      nextErrors.attachment = errors.attachment ?? labels.required;
    }

    if (Object.keys(nextErrors).length > 0) {
      setErrors(nextErrors);
      return;
    }

    setSubmitError("");
    setIsSubmitting(true);

    try {
      await onSubmit(values, mode);
      resetForm();
      onClose();
    } catch (error) {
      setSubmitError(
        error instanceof Error ? error.message : labels.submitError,
      );
    } finally {
      setIsSubmitting(false);
    }
  }

  return (
    <Dialog
      open={open}
      onClose={closeDialog}
      maxWidth={false}
      scroll="paper"
      sx={{
        "& .MuiDialog-container": {
          justifyContent: "flex-end",
          alignItems: "flex-start",
        },
      }}
      slotProps={{
        paper: {
          sx: {
            mt: 0,
            mr: 0,
            width: 795,
            maxWidth: "95vw",
            height: "calc(100vh - 16px)",
            maxHeight: "calc(100vh - 16px)",
            display: "flex",
            flexDirection: "column",
            borderRadius: "10px",
            overflow: "hidden",
            bgcolor: theme.palette.background.paper,
            color: theme.palette.text.primary,
          },
        },
      }}
    >
      <Box
        sx={{
          px: 2,
          py: 1.6,
          borderBottom: `1px solid ${getFormBorderColor(theme)}`,
          bgcolor: theme.palette.background.paper,
        }}
      >
        <Typography
          component="h2"
          sx={{
            fontSize: 18,
            fontWeight: 700,
            color: theme.palette.text.primary,
          }}
        >
          {labels.title}
        </Typography>
      </Box>

      <Box
        sx={{
          px: 2,
          py: 1.8,
          flex: 1,
          overflowY: "auto",
          maxHeight: "calc(100vh - 150px)",
          bgcolor: theme.palette.background.paper,
        }}
      >
        <CreateProgressReportDialogFields
          values={values}
          errors={errors}
          labels={labels}
          existingAttachment={existingAttachment}
          onChange={updateValue}
          onAttachmentChange={updateAttachment}
        />

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

      <Box
        sx={{
          height: 84,
          px: 2,
          display: "flex",
          alignItems: "center",
          justifyContent: "flex-end",
          gap: 2,
          flexShrink: 0,
          borderTop: `1px solid ${getFormBorderColor(theme)}`,
          bgcolor: theme.palette.background.paper,
        }}
      >
        <AppSecondaryButton
          disabled={isSubmitting}
          onClick={() => handleSubmit("draft")}
          sx={{
            width: 125,
            minWidth: 125,
            height: 40,
            minHeight: 40,
            py: 0,
            color: isFormFilled
              ? theme.palette.primary.main
              : theme.palette.text.primary,
            borderColor: isFormFilled
              ? theme.palette.primary.main
              : getFormBorderColor(theme),
            bgcolor: theme.palette.background.paper,
            fontWeight: 700,
            fontSize: 12,
            "&:hover": {
              borderColor: theme.palette.primary.main,
              bgcolor: alpha(theme.palette.primary.main, 0.08),
            },
          }}
        >
          {labels.save}
        </AppSecondaryButton>

        <AppButton
          disabled={isSubmitting}
          onClick={() => handleSubmit("sent")}
          sx={{
            width: 125,
            minWidth: 125,
            height: 40,
            minHeight: 40,
            py: 0,
            bgcolor: isFormFilled ? theme.palette.primary.main : "#7B828D",
            fontWeight: 700,
            fontSize: 12,
            "&:hover": {
              bgcolor: isFormFilled ? theme.palette.primary.dark : "#6B7280",
            },
          }}
        >
          {labels.send}
        </AppButton>
      </Box>
    </Dialog>
  );
}
