"use client";

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

import CalendarTodayOutlinedIcon from "@mui/icons-material/CalendarTodayOutlined";
import CloudUploadOutlinedIcon from "@mui/icons-material/CloudUploadOutlined";
import Box from "@mui/material/Box";
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 {
  AppFormField,
  AppFormTextField,
  getFormBorderColor,
  getFormSoftBg,
} from "@/components/ui/form";
import { PdfIcon } from "@/components/ui/icon";
import { AppTextEditor } from "@/components/ui/text-editor";
import { MeetingTimePicker } from "@/features/ministry/meeting-calendar/components/meeting-time-picker";
import type { UploadedFileMetadata } from "@/lib/document-file";

import type {
  CreateMeetingDialogLabels,
  CreateMeetingFormValues,
} from "./create-meeting-dialog-types";

type CreateMeetingDialogFieldsProps = {
  values: CreateMeetingFormValues;
  errors: Partial<Record<keyof CreateMeetingFormValues, string>>;
  labels: CreateMeetingDialogLabels;
  existingDocument?: UploadedFileMetadata | null;
  onChange: (
    field: keyof Omit<CreateMeetingFormValues, "document">,
    value: string,
  ) => void;
  onDocumentChange: (file: File | null) => void;
};

const PICKER_Z_INDEX = 1700;
const FIELD_HEIGHT = 50;
const TIME_FIELD_WIDTH = 238;

function FieldError({ message }: { message?: string }) {
  if (!message) {
    return null;
  }

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

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 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);
  if (!date) {
    return "";
  }

  return formatDate(date, "MMM dd, yyyy");
}

const pickerTriggerSx = {
  width: { xs: "100%", sm: TIME_FIELD_WIDTH },
  height: FIELD_HEIGHT,
  minHeight: FIELD_HEIGHT,
  display: "flex",
  alignItems: "center",
  gap: "8px",
  px: "12px",
  py: "8px",
  borderRadius: "6px",
  bgcolor: "#fafafa",
  border: "1px solid #f5f5f5",
  cursor: "pointer",
  textAlign: "left" as const,
  boxSizing: "border-box" as const,
  transition: "border-color 0.15s ease, background-color 0.15s ease",
  "&:hover": {
    borderColor: "#e9eaeb",
    bgcolor: "#f7f7f7",
  },
};

function MeetingDateField({
  value,
  error,
  placeholder,
  onChange,
}: {
  value: string;
  error?: boolean;
  placeholder: string;
  onChange: (value: string) => void;
}) {
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
  const open = Boolean(anchorEl);
  const displayValue = formatDateDisplay(value);

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

  function handleClose() {
    setAnchorEl(null);
  }

  return (
    <>
      <Box
        component="button"
        type="button"
        onClick={handleOpen}
        aria-label={placeholder}
        sx={{
          ...pickerTriggerSx,
          borderColor: error ? "error.main" : "#f5f5f5",
        }}
      >
        <CalendarTodayOutlinedIcon
          sx={{ fontSize: 20, color: "#717680", flexShrink: 0 }}
        />
        <Typography
          sx={{
            fontSize: 12,
            fontWeight: 400,
            lineHeight: 1.24,
            color: displayValue ? "#000000" : "#717680",
            whiteSpace: "nowrap",
            overflow: "hidden",
            textOverflow: "ellipsis",
          }}
        >
          {displayValue || placeholder}
        </Typography>
      </Box>

      <Popover
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        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(value)}
            onChange={(date) => {
              onChange(dateToDateString(date));
              handleClose();
            }}
            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",
              },
            }}
          />
        </LocalizationProvider>
      </Popover>
    </>
  );
}

function DocumentField({
  values,
  errors,
  labels,
  existingDocument,
  onDocumentChange,
}: CreateMeetingDialogFieldsProps) {
  const theme = useTheme();
  const [completedFile, setCompletedFile] = useState<File | null>(null);
  const selectedDocument = values.document;
  const documentName = selectedDocument?.name || existingDocument?.name || "";
  const documentSize = selectedDocument?.size ?? existingDocument?.size ?? 0;
  const hasDocument = Boolean(selectedDocument || existingDocument);
  const uploadCompleted = selectedDocument
    ? completedFile === selectedDocument
    : Boolean(existingDocument);

  useEffect(() => {
    if (!values.document) {
      return;
    }

    const currentFile = values.document;
    const completeTimer = window.setTimeout(
      () => setCompletedFile(currentFile),
      800,
    );

    return () => window.clearTimeout(completeTimer);
  }, [values.document]);

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

    onDocumentChange(nextFile);
  }

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

  function handleDrop(event: DragEvent<HTMLLabelElement>) {
    event.preventDefault();
    selectFile(event.dataTransfer.files?.[0]);
  }

  return (
    <AppFormField
      label={
        <>
          {labels.document}
          <Typography component="span" sx={{ color: "#f04438" }}>
            {" "}
            *
          </Typography>
        </>
      }
    >
      {hasDocument ? (
        <Box
          sx={{
            display: "flex",
            alignItems: "center",
            gap: "22px",
            width: "100%",
          }}
        >
          <Box
            sx={{
              position: "relative",
              width: 287,
              minWidth: 287,
              height: 62,
              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: 160,
              }}
            >
              <PdfIcon sx={{ fontSize: 40, flexShrink: 0 }} />
              <Box sx={{ minWidth: 0 }}>
                <Typography
                  noWrap
                  sx={{
                    fontSize: 12,
                    fontWeight: 500,
                    color: "text.primary",
                    lineHeight: 1,
                  }}
                >
                  {documentName.replace(/\.pdf$/i, "") ||
                    "Meeting request DOC"}
                </Typography>
                <Typography
                  sx={{
                    mt: 1.5,
                    fontSize: 12,
                    lineHeight: 1.24,
                    fontWeight: 400,
                    color: "text.secondary",
                  }}
                >
                  {formatFileSize(documentSize)}
                </Typography>
              </Box>
            </Box>

            <Box
              sx={{
                position: "absolute",
                left: "185px",
                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: uploadCompleted ? "100%" : "45%",
                    height: "100%",
                    borderRadius: "16px",
                    bgcolor: "#22C55E",
                    transition: "width 0.8s ease",
                  }}
                />
              </Box>
            </Box>
          </Box>

          <Box
            component="label"
            onDragOver={(event: DragEvent<HTMLLabelElement>) =>
              event.preventDefault()
            }
            onDrop={handleDrop}
            sx={{
              width: 77,
              minWidth: 77,
              height: 62,
              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"
              onChange={handleFileChange}
            />
          </Box>
        </Box>
      ) : (
        <Box
          component="label"
          onDragOver={(event: DragEvent<HTMLLabelElement>) =>
            event.preventDefault()
          }
          onDrop={handleDrop}
          sx={{
            width: "100%",
            height: 62,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            borderRadius: "6px",
            border: `1px dashed ${
              errors.document
                ? 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"
            onChange={handleFileChange}
          />
        </Box>
      )}
      <FieldError message={errors.document} />
    </AppFormField>
  );
}

export function CreateMeetingDialogFields({
  values,
  errors,
  labels,
  existingDocument,
  onChange,
  onDocumentChange,
}: CreateMeetingDialogFieldsProps) {
  const theme = useTheme();

  const timePickerSx = {
    width: { xs: "100%", sm: TIME_FIELD_WIDTH },
    "& .MuiOutlinedInput-root": {
      height: FIELD_HEIGHT,
      minHeight: FIELD_HEIGHT,
      borderRadius: "6px",
      bgcolor: "#fafafa",
      px: "12px",
      gap: "8px",
      "& fieldset": {
        borderColor: "#f5f5f5",
      },
      "&:hover fieldset": {
        borderColor: "#e9eaeb",
      },
      "&.Mui-focused fieldset": {
        borderColor: theme.palette.primary.main,
        borderWidth: 1,
      },
    },
    "& .MuiInputBase-input": {
      fontSize: 12,
      fontWeight: 400,
      lineHeight: 1.24,
      py: 0,
      px: 0,
      color: "#000000",
      "&::placeholder": {
        color: "#717680",
        opacity: 1,
      },
    },
    "& .MuiInputAdornment-root": {
      margin: 0,
      "& .MuiSvgIcon-root": {
        fontSize: 20,
        color: "#717680",
      },
    },
  } as const;

  return (
    <Box sx={{ display: "flex", flexDirection: "column", gap: "22px" }}>
      <AppFormField
        label={
          <>
            {labels.name}
            <Typography component="span" sx={{ color: "#f04438" }}>
              {" "}
              *
            </Typography>
          </>
        }
      >
        <AppFormTextField
          value={values.name}
          placeholder={labels.namePlaceholder}
          error={Boolean(errors.name)}
          onChange={(event) => onChange("name", event.target.value)}
          sx={{
            "& .MuiOutlinedInput-root": {
              height: FIELD_HEIGHT,
              borderRadius: "6px",
              fontSize: 13,
              fontWeight: 500,
            },
          }}
        />
        <FieldError message={errors.name} />
      </AppFormField>

      <AppFormField
        label={
          <>
            {labels.description}
            <Typography component="span" sx={{ color: "#f04438" }}>
              {" "}
              *
            </Typography>
          </>
        }
      >
        <AppTextEditor
          value={values.description}
          onChange={(value) => onChange("description", value)}
          placeholder={labels.descriptionPlaceholder}
          minRows={4}
        />
        <FieldError message={errors.description} />
      </AppFormField>

      <Box
        sx={{
          display: "flex",
          flexWrap: { xs: "wrap", sm: "nowrap" },
          alignItems: "flex-start",
          justifyContent: "space-between",
          gap: { xs: 2, sm: 0 },
          width: "100%",
        }}
      >
        <AppFormField
          label={
            <>
              {labels.date}
              <Typography component="span" sx={{ color: "#f04438" }}>
                {" "}
                *
              </Typography>
            </>
          }
          sx={{
            width: { xs: "100%", sm: TIME_FIELD_WIDTH },
            display: "flex",
            flexDirection: "column",
            gap: "12px",
          }}
        >
          <MeetingDateField
            value={values.date}
            error={Boolean(errors.date)}
            placeholder={labels.datePlaceholder}
            onChange={(value) => onChange("date", value)}
          />
          <FieldError message={errors.date} />
        </AppFormField>

        <AppFormField
          label={
            <>
              {labels.startTime}
              <Typography component="span" sx={{ color: "#f04438" }}>
                {" "}
                *
              </Typography>
            </>
          }
          sx={{
            width: { xs: "100%", sm: TIME_FIELD_WIDTH },
            display: "flex",
            flexDirection: "column",
            gap: "12px",
          }}
        >
          <MeetingTimePicker
            value={values.startTime}
            onChange={(value) => onChange("startTime", value)}
            error={Boolean(errors.startTime)}
            inputSx={timePickerSx}
          />
          <FieldError message={errors.startTime} />
        </AppFormField>

        <AppFormField
          label={
            <>
              {labels.endTime}
              <Typography component="span" sx={{ color: "#f04438" }}>
                {" "}
                *
              </Typography>
            </>
          }
          sx={{
            width: { xs: "100%", sm: TIME_FIELD_WIDTH },
            display: "flex",
            flexDirection: "column",
            gap: "12px",
          }}
        >
          <MeetingTimePicker
            value={values.endTime}
            onChange={(value) => onChange("endTime", value)}
            error={Boolean(errors.endTime)}
            inputSx={timePickerSx}
          />
          <FieldError message={errors.endTime} />
        </AppFormField>
      </Box>

      <AppFormField
        label={
          <>
            {labels.location}
            <Typography component="span" sx={{ color: "#f04438" }}>
              {" "}
              *
            </Typography>
          </>
        }
      >
        <AppFormTextField
          value={values.location}
          placeholder={labels.locationPlaceholder}
          error={Boolean(errors.location)}
          onChange={(event) => onChange("location", event.target.value)}
          sx={{
            "& .MuiOutlinedInput-root": {
              height: FIELD_HEIGHT,
              borderRadius: "6px",
              fontSize: 13,
              fontWeight: 500,
            },
          }}
        />
        <FieldError message={errors.location} />
      </AppFormField>

      <DocumentField
        values={values}
        errors={errors}
        labels={labels}
        existingDocument={existingDocument}
        onChange={onChange}
        onDocumentChange={onDocumentChange}
      />
    </Box>
  );
}
