"use client";

import { useState, type MouseEvent } from "react";

import CalendarTodayOutlinedIcon from "@mui/icons-material/CalendarTodayOutlined";
import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import Dialog from "@mui/material/Dialog";
import Popover from "@mui/material/Popover";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import { DateCalendar } from "@mui/x-date-pickers/DateCalendar";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { format as formatDate } from "date-fns";
import { enUS } from "date-fns/locale/en-US";

import { AppButton, AppSecondaryButton } from "@/components/ui/button";

export type SetDeadlineDialogLabels = {
  title: string;
  date: string;
  finalDeadline: string;
  datePlaceholder: string;
  today: string;
  save: string;
  send: string;
  required: string;
  finalDeadlineAfterDate: string;
  submitError: string;
};

export type ProgressReportDeadlineDialogSlot = "FIRST" | "SECOND" | "FINAL";
export type SetDeadlineSlot = "SECOND" | "FINAL";

type SetDeadlineDialogProps = {
  open: boolean;
  labels: SetDeadlineDialogLabels;
  title?: string;
  slot: ProgressReportDeadlineDialogSlot;
  initialDate?: string;
  onClose: () => void;
  onSave?: (date: string) => Promise<void>;
  onSend?: (date: string) => Promise<void>;
};

type DeadlineErrors = { date?: string };

const DIALOG_WIDTH = 416;
const DIALOG_HEIGHT = 640;
const HEADER_HEIGHT = 67;
const FOOTER_HEIGHT = 75;
const CONTENT_PADDING_X = 18;
const PICKER_Z_INDEX = 1500;

function dateStringToDate(value: string) {
  if (!value) return null;

  const [year, month, day] = value.split("-").map(Number);
  const date = new Date(year, month - 1, day);

  return Number.isNaN(date.getTime()) ? null : date;
}

function dateToDateString(date: Date | null) {
  if (!date) return "";

  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");

  return `${year}-${month}-${day}`;
}

function formatDateDisplay(value: string) {
  const date = dateStringToDate(value);
  return date ? formatDate(date, "MMM dd, yyyy") : "";
}

function DeadlineDateField({
  label,
  value,
  error,
  placeholder,
  required = false,
  onOpen,
}: {
  label: string;
  value: string;
  error?: string;
  placeholder: string;
  required?: boolean;
  onOpen: (event: MouseEvent<HTMLElement>) => void;
}) {
  const displayValue = formatDateDisplay(value);

  return (
    <Box>
      <Typography
        sx={{ fontSize: 13, fontWeight: 500, color: "#414651", lineHeight: 1 }}
      >
        {label}
        {required ? (
          <Typography component="span" sx={{ color: "#f04438" }}>
            {" "}
            *
          </Typography>
        ) : null}
      </Typography>

      <Box
        component="button"
        type="button"
        onClick={onOpen}
        aria-label={placeholder}
        sx={{
          width: "100%",
          height: 50,
          mt: "12px",
          display: "flex",
          alignItems: "center",
          gap: "8px",
          px: "12px",
          borderRadius: "6px",
          bgcolor: "#fafafa",
          border: `1px solid ${error ? "#f04438" : "#f5f5f5"}`,
          cursor: "pointer",
          textAlign: "left",
          font: "inherit",
        }}
      >
        <CalendarTodayOutlinedIcon
          sx={{ fontSize: 20, color: "#717680", flexShrink: 0 }}
        />
        <Typography
          sx={{
            fontSize: 12,
            fontWeight: 400,
            lineHeight: 1.24,
            color: displayValue ? "#000000" : "#717680",
          }}
        >
          {displayValue || placeholder}
        </Typography>
      </Box>

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

export function SetDeadlineDialog({
  open,
  labels,
  title,
  slot,
  initialDate = "",
  onClose,
  onSave,
  onSend,
}: SetDeadlineDialogProps) {
  const theme = useTheme();
  const [date, setDate] = useState(initialDate);
  const [errors, setErrors] = useState<DeadlineErrors>({});
  const [submitError, setSubmitError] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);

  const calendarOpen = Boolean(anchorEl);
  const selectedValue = date;
  // The one field is named after the slot it fills.
  const fieldLabel = slot === "FINAL" ? labels.finalDeadline : labels.date;

  function closeDialog() {
    if (isSubmitting) return;

    setDate(initialDate);
    setErrors({});
    setSubmitError("");
    setAnchorEl(null);
    onClose();
  }

  function openCalendar(event: MouseEvent<HTMLElement>) {
    setAnchorEl(event.currentTarget);
  }

  function handleCloseCalendar() {
    setAnchorEl(null);
  }

  function handleSelectDate(nextDate: Date | null) {
    if (!nextDate) return;

    setDate(dateToDateString(nextDate));
    setErrors({});
    handleCloseCalendar();
  }

  function validate() {
    const nextErrors: DeadlineErrors = {};

    if (!date) nextErrors.date = labels.required;

    setErrors(nextErrors);
    return Object.keys(nextErrors).length === 0;
  }

  async function submit(shouldSend: boolean) {
    if (isSubmitting || !validate()) return;

    setSubmitError("");
    setIsSubmitting(true);

    try {
      if (shouldSend) {
        await onSend?.(date);
      } else {
        await onSave?.(date);
      }
      setIsSubmitting(false);
      closeDialog();
    } catch (requestError) {
      setSubmitError(
        requestError instanceof Error
          ? requestError.message
          : labels.submitError,
      );
      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)",
            maxHeight: "calc(100vh - 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",
          flexShrink: 0,
          borderBottom: `1px solid ${
            theme.palette.mode === "dark" ? alpha("#ffffff", 0.12) : "#f5f5f5"
          }`,
        }}
      >
        <Typography
          sx={{
            fontSize: 20,
            fontWeight: 500,
            letterSpacing: "-0.4px",
            color: theme.palette.text.primary,
          }}
        >
          {title || labels.title}
        </Typography>
      </Box>

      <Box
        sx={{
          flex: 1,
          px: `${CONTENT_PADDING_X}px`,
          pt: "22px",
          pb: "22px",
          display: "flex",
          flexDirection: "column",
          gap: "22px",
        }}
      >
        <DeadlineDateField
          label={fieldLabel}
          value={date}
          error={errors.date}
          placeholder={labels.datePlaceholder}
          required
          onOpen={openCalendar}
        />

        {submitError ? <Alert severity="error">{submitError}</Alert> : null}
      </Box>

      <Box
        sx={{
          height: FOOTER_HEIGHT,
          px: "18px",
          display: "flex",
          alignItems: "center",
          justifyContent: "flex-end",
          gap: 1.5,
          flexShrink: 0,
          borderTop: `1px solid ${
            theme.palette.mode === "dark" ? alpha("#ffffff", 0.12) : "#f5f5f5"
          }`,
        }}
      >
        <AppSecondaryButton
          disabled={isSubmitting}
          onClick={() => submit(false)}
          sx={{ width: 110, minWidth: 110, height: 40, minHeight: 40 }}
        >
          {labels.save}
        </AppSecondaryButton>
        <AppButton
          disabled={isSubmitting}
          onClick={() => submit(true)}
          sx={{
            width: 110,
            minWidth: 110,
            height: 40,
            minHeight: 40,
            borderRadius: "6px",
            fontSize: 13,
            fontWeight: 500,
          }}
        >
          {labels.send}
        </AppButton>
      </Box>

      <Popover
        open={calendarOpen}
        anchorEl={anchorEl}
        onClose={handleCloseCalendar}
        anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
        transformOrigin={{ vertical: "top", horizontal: "left" }}
        sx={{ zIndex: PICKER_Z_INDEX }}
        slotProps={{
          paper: {
            sx: {
              mt: 0.75,
              width: 280,
              borderRadius: "11px",
              border: "1px solid #e9eaeb",
              boxShadow: "0 4px 16px rgba(16, 24, 40, 0.14)",
              overflow: "hidden",
            },
          },
        }}
      >
        <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={enUS}>
          <DateCalendar
            value={dateStringToDate(selectedValue)}
            onChange={handleSelectDate}
            sx={{
              width: 280,
              maxHeight: 322,
              "& .MuiPickersCalendarHeader-root": {
                minHeight: 40,
                mt: 1,
                mb: 0.5,
                px: 1.25,
              },
              "& .MuiPickersCalendarHeader-label": {
                fontSize: 12,
                fontWeight: 500,
              },
              "& .MuiDayCalendar-weekDayLabel": {
                width: 36,
                height: 30,
                fontSize: 11,
              },
              "& .MuiPickersDay-root": {
                width: 36,
                height: 36,
                fontSize: 11,
                borderRadius: "8px",
              },
              "& .MuiPickersDay-root.Mui-selected": {
                bgcolor: "#9747ff",
                color: "#ffffff",
              },
              "& .MuiPickersDay-root.Mui-selected:hover, & .MuiPickersDay-root.Mui-selected:focus":
                {
                  bgcolor: "#8639e8",
                },
            }}
          />
        </LocalizationProvider>
      </Popover>
    </Dialog>
  );
}
