import React, { useCallback, useEffect, useState } from "react";

import {
  Alert,
  Box,
  Button,
  CircularProgress,
  Divider,
  IconButton,
  Popover,
  Stack,
  Tooltip,
  Typography,
} from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
import DoneIcon from "@mui/icons-material/Done";

import { api, getApiErrorMessage } from "../api";
import { useI18n } from "../i18n/I18nProvider";
import { notificationDateLabel, UserNotification } from "../notifications";

type Props = {
  anchorEl: HTMLElement | null;
  onClose: () => void;
  onNavigate: (path: string) => void;
  onChanged: () => void;
};

export default function NotificationsPopover({ anchorEl, onClose, onNavigate, onChanged }: Props) {
  const { t } = useI18n();
  const open = Boolean(anchorEl);
  const [notifications, setNotifications] = useState<UserNotification[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [busyId, setBusyId] = useState<string | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const response = await api.get<UserNotification[]>("/notifications?limit=10");
      setNotifications(response.data ?? []);
      setError(null);
    } catch (requestError) {
      setError(getApiErrorMessage(requestError, t("notificationsLoadFailed")));
    } finally {
      setLoading(false);
    }
  }, [t]);

  useEffect(() => {
    if (open) void load();
  }, [load, open]);

  const markRead = async (notification: UserNotification) => {
    if (notification.readAtUtc || busyId) return;
    setBusyId(notification.id);
    try {
      await api.post(`/notifications/${notification.id}/read`);
      setNotifications((items) => items.map((item) => item.id === notification.id
        ? { ...item, readAtUtc: new Date().toISOString() }
        : item));
      setError(null);
      onChanged();
    } catch (requestError) {
      setError(getApiErrorMessage(requestError, t("notificationsActionFailed")));
    } finally {
      setBusyId(null);
    }
  };

  const dismiss = async (notification: UserNotification) => {
    if (busyId) return;
    setBusyId(notification.id);
    try {
      await api.delete(`/notifications/${notification.id}`);
      setNotifications((items) => items.filter((item) => item.id !== notification.id));
      setError(null);
      onChanged();
    } catch (requestError) {
      setError(getApiErrorMessage(requestError, t("notificationsActionFailed")));
    } finally {
      setBusyId(null);
    }
  };

  const openNotification = async (notification: UserNotification) => {
    if (!notification.linkPath) return;
    if (!notification.readAtUtc) await markRead(notification);
    onClose();
    onNavigate(notification.linkPath);
  };

  return (
    <Popover
      open={open}
      anchorEl={anchorEl}
      onClose={onClose}
      anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      slotProps={{
        paper: {
          "aria-label": t("notificationsPanel"),
          sx: {
            mt: 1,
            width: "min(420px, calc(100vw - 24px))",
            maxHeight: "min(70vh, 600px)",
            borderRadius: 3,
            overflow: "hidden",
          },
        },
      }}
    >
      <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ px: 2, py: 1.5 }}>
        <Box>
          <Typography sx={{ fontWeight: 900 }}>{t("notifications")}</Typography>
          <Typography variant="caption" color="text.secondary">{t("notificationsRecent")}</Typography>
        </Box>
        <Tooltip title={t("close")}>
          <IconButton size="small" aria-label={t("close")} onClick={onClose}><CloseIcon fontSize="small" /></IconButton>
        </Tooltip>
      </Stack>
      <Divider />

      <Box sx={{ overflowY: "auto", maxHeight: "min(52vh, 450px)", p: 1 }}>
        {loading ? <Box sx={{ py: 4, display: "grid", placeItems: "center" }}><CircularProgress size={28} aria-label={t("loading")} /></Box> : null}
        {error ? <Alert severity="error" action={<Button color="inherit" size="small" onClick={() => void load()}>{t("retry")}</Button>} sx={{ m: 0.5 }}>{error}</Alert> : null}
        {!loading && !error && notifications.length === 0 ? (
          <Box sx={{ py: 4, px: 2, textAlign: "center" }}>
            <Typography sx={{ fontWeight: 800 }}>{t("notificationsEmptyTitle")}</Typography>
            <Typography variant="body2" color="text.secondary">{t("notificationsEmptyBody")}</Typography>
          </Box>
        ) : null}
        {!loading ? notifications.map((notification) => (
          <Box
            key={notification.id}
            sx={{
              p: 1.5,
              mb: 0.75,
              borderRadius: 2.5,
              border: "1px solid",
              borderColor: "divider",
              bgcolor: notification.readAtUtc ? "transparent" : "action.selected",
              opacity: notification.readAtUtc ? 0.82 : 1,
            }}
          >
            <Typography sx={{ fontWeight: notification.readAtUtc ? 700 : 900, overflowWrap: "anywhere" }}>{notification.title}</Typography>
            <Typography variant="body2" color="text.secondary" sx={{ mt: 0.25, overflowWrap: "anywhere" }}>{notification.message}</Typography>
            <Typography variant="caption" color="text.secondary">{notificationDateLabel(notification.createdAtUtc)}</Typography>
            <Stack direction="row" spacing={0.5} alignItems="center" sx={{ mt: 0.75, flexWrap: "wrap" }}>
              {notification.linkPath ? <Button size="small" onClick={() => void openNotification(notification)}>{t("notificationsOpen")}</Button> : null}
              {!notification.readAtUtc ? (
                <Button size="small" startIcon={<DoneIcon />} disabled={busyId !== null} onClick={() => void markRead(notification)}>{t("notificationsMarkRead")}</Button>
              ) : null}
              <Button size="small" color="inherit" startIcon={<DeleteOutlineIcon />} disabled={busyId !== null} onClick={() => void dismiss(notification)}>{t("notificationsDismiss")}</Button>
            </Stack>
          </Box>
        )) : null}
      </Box>

      <Divider />
      <Box sx={{ p: 1 }}>
        <Button fullWidth onClick={() => { onClose(); onNavigate("/operations"); }}>{t("notificationsViewAll")}</Button>
      </Box>
    </Popover>
  );
}
