"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 { CreateMeetingDialogFields } from "./create-meeting-dialog-fields";
import type {
  CreateMeetingDialogLabels,
  CreateMeetingFormValues,
  CreateMeetingSubmitMode,
  MeetingFormInitialValues,
} from "./create-meeting-dialog-types";

type CreateMeetingDialogProps = {
  open: boolean;
  labels: CreateMeetingDialogLabels;
  title?: string;
  defaultName?: string;
  initialValues?: MeetingFormInitialValues;
  existingDocument?: UploadedFileMetadata | null;
  onClose: () => void;
  onSubmit?: (
    values: CreateMeetingFormValues,
    mode: CreateMeetingSubmitMode,
  ) => Promise<void>;
};

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

const MAX_PDF_SIZE = 10 * 1024 * 1024;

function getInitialForm(
  defaultName = "",
  initialValues?: MeetingFormInitialValues,
): CreateMeetingFormValues {
  return {
    name: defaultName,
    description: "",
    date: "",
    startTime: "",
    endTime: "",
    location: "",
    document: null,
    ...initialValues,
  };
}

function isHtmlEmpty(value: string) {
  return value.replace(/<[^>]*>/g, "").trim() === "";
}

export function CreateMeetingDialog({
  open,
  labels,
  title,
  defaultName = "",
  initialValues,
  existingDocument,
  onClose,
  onSubmit,
}: CreateMeetingDialogProps) {
  const theme = useTheme();
  const [values, setValues] = useState<CreateMeetingFormValues>(() =>
    getInitialForm(defaultName, initialValues),
  );
  const [errors, setErrors] = useState<FormErrors>({});
  const [submitError, setSubmitError] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);

  const hasStoredDocument = Boolean(existingDocument);
  const isFormFilled =
    values.name.trim() !== "" &&
    !isHtmlEmpty(values.description) &&
    values.date !== "" &&
    values.startTime !== "" &&
    values.endTime !== "" &&
    values.location.trim() !== "" &&
    (values.document !== null || hasStoredDocument);

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

  function closeDialog() {
    if (isSubmitting) return;

    resetForm();
    onClose();
  }

  function updateValue(
    field: keyof Omit<CreateMeetingFormValues, "document">,
    value: string,
  ) {
    setValues((current) => ({ ...current, [field]: value }));
    setErrors((current) => ({ ...current, [field]: undefined }));
  }

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

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

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

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

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

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

    const nextErrors: FormErrors = {};

    if (!values.name.trim()) nextErrors.name = labels.required;
    if (isHtmlEmpty(values.description))
      nextErrors.description = labels.required;
    if (!values.date) nextErrors.date = labels.required;
    if (!values.startTime) nextErrors.startTime = labels.required;
    if (!values.endTime) nextErrors.endTime = labels.required;
    if (!values.location.trim()) nextErrors.location = labels.required;
    if (!values.document && !hasStoredDocument) {
      nextErrors.document = errors.document ?? labels.required;
    }

    if (
      values.startTime &&
      values.endTime &&
      values.endTime <= values.startTime
    ) {
      nextErrors.endTime = labels.endTimeBeforeStart;
    }

    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={{
        backdrop: {
          sx: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
        },
        paper: {
          sx: {
            mt: 0,
            mr: 0,
            width: 795,
            maxWidth: "95vw",
            height: { xs: "calc(100vh - 16px)", sm: 960 },
            maxHeight: "calc(100vh - 16px)",
            display: "flex",
            flexDirection: "column",
            borderRadius: "16px",
            overflow: "hidden",
            bgcolor: theme.palette.background.paper,
            color: theme.palette.text.primary,
          },
        },
      }}
    >
      <Box
        sx={{
          height: 67,
          px: "22px",
          display: "flex",
          alignItems: "center",
          flexShrink: 0,
          borderBottom: `1px solid ${getFormBorderColor(theme)}`,
          bgcolor: theme.palette.background.paper,
        }}
      >
        <Typography
          component="h2"
          sx={{
            fontSize: 20,
            fontWeight: 500,
            letterSpacing: "-0.4px",
            color: theme.palette.text.primary,
          }}
        >
          {title || labels.title}
        </Typography>
      </Box>

      <Box
        sx={{
          px: "18px",
          py: "22px",
          flex: 1,
          overflowY: "auto",
          bgcolor: theme.palette.background.paper,
        }}
      >
        <CreateMeetingDialogFields
          values={values}
          errors={errors}
          labels={labels}
          existingDocument={existingDocument}
          onChange={updateValue}
          onDocumentChange={updateDocument}
        />

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

      <Box
        sx={{
          height: 84,
          px: "22px",
          display: "flex",
          alignItems: "center",
          justifyContent: "flex-end",
          gap: "22px",
          flexShrink: 0,
          borderTop: `1px solid ${getFormBorderColor(theme)}`,
          bgcolor: theme.palette.background.paper,
        }}
      >
        <AppSecondaryButton
          disabled={isSubmitting}
          onClick={() => handleSubmit("draft")}
          sx={{
            width: 150,
            minWidth: 150,
            height: 40,
            minHeight: 40,
            px: "54px",
            py: "12px",
            borderRadius: "6px",
            color: "#153858",
            borderColor: "#d5d7da",
            bgcolor: theme.palette.background.paper,
            fontWeight: 500,
            fontSize: 13,
            "&:hover": {
              borderColor: theme.palette.primary.main,
              bgcolor: alpha(theme.palette.primary.main, 0.08),
            },
          }}
        >
          {labels.save}
        </AppSecondaryButton>

        <AppButton
          disabled={isSubmitting}
          onClick={() => handleSubmit("sent")}
          sx={{
            minWidth: 0,
            height: 40,
            minHeight: 40,
            px: "59px",
            py: "12px",
            borderRadius: "6px",
            bgcolor: isFormFilled ? "#1a64a8" : "#717680",
            fontWeight: 500,
            fontSize: 13,
            boxShadow: "none",
            "&:hover": {
              bgcolor: isFormFilled ? "#155489" : "#5f6773",
              boxShadow: "none",
            },
          }}
        >
          {labels.send}
        </AppButton>
      </Box>
    </Dialog>
  );
}
