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

import {
  Alert,
  Box,
  Button,
  Chip,
  LinearProgress,
  Paper,
  Stack,
  Typography,
} from "@mui/material";

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

type Operation = {
  id: string;
  taskType: string;
  status: string;
  subjectType?: string | null;
  createdAtUtc: string;
  completedAtUtc?: string | null;
  cancellationRequestedAtUtc?: string | null;
  progressStage?: string | null;
  progressPercent?: number | null;
  failureCategory?: string | null;
  canCancel: boolean;
  canRetry: boolean;
};

const statusLabel = (value: string) => value.replaceAll("_", " ");

export default function OperationsPage() {
  const { language, t } = useI18n();
  const [operations, setOperations] = useState<Operation[]>([]);
  const [notifications, setNotifications] = useState<UserNotification[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [busyKey, setBusyKey] = useState<string | null>(null);

  const load = useCallback(async (showLoading = false) => {
    if (showLoading) setLoading(true);
    try {
      const [operationResponse, notificationResponse] = await Promise.all([
        api.get<Operation[]>("/operations?limit=50"),
        api.get<UserNotification[]>("/notifications?limit=50"),
      ]);
      setOperations(operationResponse.data ?? []);
      setNotifications(notificationResponse.data ?? []);
      setError(null);
    } catch (requestError) {
      setError(getApiErrorMessage(requestError, t("operationsLoadFailed")));
    } finally {
      setLoading(false);
    }
  }, [t]);

  useEffect(() => {
    void load();
    const interval = window.setInterval(() => void load(), 15000);
    return () => window.clearInterval(interval);
  }, [load]);

  const runAction = async (key: string, action: () => Promise<unknown>, notificationsChanged = false) => {
    if (busyKey) return;
    setBusyKey(key);
    try {
      await action();
      await load();
      if (notificationsChanged) window.dispatchEvent(new Event("notifications-changed"));
    } catch (requestError) {
      setError(getApiErrorMessage(requestError, t("operationsActionFailed")));
    } finally {
      setBusyKey(null);
    }
  };

  return (
    <Stack spacing={2}>
      <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 2, flexWrap: "wrap" }}>
        <Typography color="text.secondary">{t("operationsSubtitle")}</Typography>
        <Button variant="outlined" onClick={() => void load(true)} disabled={loading}>{t("refresh")}</Button>
      </Box>

      {error ? <Alert severity="error" aria-live="polite">{error}</Alert> : null}
      {loading ? <LinearProgress aria-label={t("operationsLoading")} /> : null}

      <Paper component="section" aria-labelledby="notifications-heading" sx={{ p: { xs: 2, sm: 3 } }}>
        <Typography id="notifications-heading" variant="h6" sx={{ mb: 2 }}>{t("notifications")}</Typography>
        {notifications.length === 0 && !loading ? <Typography color="text.secondary">{t("operationsNoNotifications")}</Typography> : null}
        <Stack spacing={1.5}>
          {notifications.map((notification) => (
            <Box key={notification.id} sx={{ p: 2, border: "1px solid", borderColor: "divider", borderRadius: 2, opacity: notification.readAtUtc ? 0.75 : 1 }}>
              <Typography sx={{ fontWeight: notification.readAtUtc ? 600 : 800 }}>{notification.title}</Typography>
              <Typography color="text.secondary">{notification.message}</Typography>
              <Typography variant="caption" color="text.secondary">{notificationDateLabel(notification.createdAtUtc, language === "nb" ? "nb-NO" : "en")}</Typography>
              <Stack direction="row" spacing={1} sx={{ mt: 1, flexWrap: "wrap" }}>
                {!notification.readAtUtc ? (
                  <Button size="small" disabled={busyKey !== null} onClick={() => void runAction(`read-${notification.id}`, () => api.post(`/notifications/${notification.id}/read`), true)}>
                    {t("notificationsMarkRead")}
                  </Button>
                ) : null}
                <Button size="small" color="inherit" disabled={busyKey !== null} onClick={() => void runAction(`dismiss-${notification.id}`, () => api.delete(`/notifications/${notification.id}`), true)}>
                  {t("notificationsDismiss")}
                </Button>
              </Stack>
            </Box>
          ))}
        </Stack>
      </Paper>

      <Paper component="section" aria-labelledby="operations-heading" sx={{ p: { xs: 2, sm: 3 } }}>
        <Typography id="operations-heading" variant="h6" sx={{ mb: 2 }}>{t("operations")}</Typography>
        {operations.length === 0 && !loading ? <Typography color="text.secondary">{t("operationsEmpty")}</Typography> : null}
        <Stack spacing={1.5}>
          {operations.map((operation) => (
            <Box key={operation.id} sx={{ p: 2, border: "1px solid", borderColor: "divider", borderRadius: 2 }}>
              <Box sx={{ display: "flex", justifyContent: "space-between", gap: 1, flexWrap: "wrap" }}>
                <Typography sx={{ fontWeight: 800, overflowWrap: "anywhere" }}>{operation.taskType}</Typography>
                <Chip size="small" label={statusLabel(operation.status)} />
              </Box>
              <Typography variant="caption" color="text.secondary">{t("operationsStarted", { date: notificationDateLabel(operation.createdAtUtc, language === "nb" ? "nb-NO" : "en") })}</Typography>
              {operation.progressStage ? <Typography sx={{ mt: 1 }}>{operation.progressStage}</Typography> : null}
              {operation.progressPercent != null ? <LinearProgress variant="determinate" value={operation.progressPercent} aria-label={t("operationsProgress", { task: operation.taskType })} sx={{ mt: 1 }} /> : null}
              {operation.cancellationRequestedAtUtc ? <Typography color="text.secondary" sx={{ mt: 1 }}>{t("operationsCancellationRequested")}</Typography> : null}
              {operation.failureCategory ? <Alert severity="error" sx={{ mt: 1 }}>{t("operationsFailed", { category: statusLabel(operation.failureCategory) })}</Alert> : null}
              <Stack direction="row" spacing={1} sx={{ mt: 1, flexWrap: "wrap" }}>
                {operation.canCancel ? (
                  <Button size="small" color="error" disabled={busyKey !== null} onClick={() => void runAction(`cancel-${operation.id}`, () => api.post(`/operations/${operation.id}/cancel`))}>
                    {t("cancel")}
                  </Button>
                ) : null}
                {operation.canRetry ? (
                  <Button size="small" variant="outlined" disabled={busyKey !== null} onClick={() => void runAction(`retry-${operation.id}`, () => api.post(`/operations/${operation.id}/retry`), true)}>
                    {t("retry")}
                  </Button>
                ) : null}
              </Stack>
            </Box>
          ))}
        </Stack>
      </Paper>
    </Stack>
  );
}
