import React, { useState, useContext } from "react";
import { useNavigate } from "react-router-dom";
import { usePipelineMappings } from "../../Queries.jsx";
import StoreContext from "../../ctx/StoreContext.jsx";
import JobContext, { jobStatus } from "../../ctx/JobContext.jsx";

import Accordion from "@mui/material/Accordion";
import AccordionDetails from "@mui/material/AccordionDetails";
import AccordionSummary from "@mui/material/AccordionSummary";
import Typography from "@mui/material/Typography";

import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";

import IconButton from "@mui/material/IconButton";
import DeleteIcon from "@mui/icons-material/Delete";
import NotificationsIcon from "@mui/icons-material/Notifications";
import ReplayIcon from "@mui/icons-material/Replay";
import PhotoCameraIcon from "@mui/icons-material/PhotoCamera";

import CheckIcon from "@mui/icons-material/Check";
import ClearIcon from "@mui/icons-material/Clear";
import ViewColumnIcon from "@mui/icons-material/ViewColumn";
import PendingIcon from "@mui/icons-material/Pending";
import VisibilityIcon from "@mui/icons-material/Visibility";
import DoNotDisturbIcon from "@mui/icons-material/DoNotDisturb";

import Badge from "@mui/material/Badge";
import Stack from "@mui/material/Stack";
import Box from "@mui/material/Box";

import {
  selectBranch,
  asTree,
  asBranches,
  as1d,
} from "../../../lib/jobs/pipelines.js";

const stopPropagation = (e) => e.stopPropagation() && e.preventDefault();

export default function FailingBox(props) {
  const { failingTest, silenceClick } = props;
  const {
    class: testClass,
    name: testName,
    timestamp,
    silencedUntil,
    type,
    dailyFails,
    screenshot: screenshotUrl,
    recentResults,
    failedMessage,
    isPipeline,
    jobStatus: testJobStatus,
    job,
    pipeline,
  } = failingTest;

  const navigate = useNavigate();
  const { data: pipelineMappings, isLoading } = usePipelineMappings();
  const { jobFactory } = useContext(JobContext);

  const { state: store, updateStore, removeFailure } = useContext(StoreContext);

  const [open, setOpen] = useState(false);
  const toggleOpen = () => setOpen(!open);

  const [removeOpen, setRemoveOpen] = useState(false);
  const removeClick = () => setRemoveOpen(!removeOpen);

  const handleRemoveClose = (confirmed) => (e) => {
    stopPropagation(e);
    setRemoveOpen(false);
    if (!confirmed) return;
    removeFailure(failingTest);
  };

  function badgeColor() {
    if (dailyFails === 1) return "primary";
    else if (dailyFails === 2) return "secondary";
    else if (dailyFails < 6) return "warning";
    return "error";
  }

  const retryPipelineTest = () => {
    const primaries = pipelineMappings.filter((m) => m.includes(testName));
    const builderCache = {
      branches: asBranches(primaries),
      tree: asTree(primaries),
      selectedBranches: as1d(primaries),
      isTriage: true,
    };
    const pipeline = jobFactory(builderCache);
    if (store.focusJob) navigate(`/qualiteer/jobs#p${pipeline.id}`);
  };

  const retryTest = () => {
    if (isPipeline) return retryPipelineTest();
    const jobId = jobFactory({ testNames: [testName], isTriage: true });
    if (store.focusJob) navigate(`/qualiteer/jobs#${jobId}`);
  };

  const navigateToJob = () => {
    if (pipeline) return navigate(`/qualiteer/jobs#p${pipeline.id}`);
    navigate(`/qualiteer/jobs#${job.jobId}`);
  };

  const jobOnClick = () => {
    if (pipeline) return navigateToJob;
    if (!job) return retryTest;
    switch (job.status) {
      case jobStatus.OK:
        return navigateToJob;
      case jobStatus.ERROR:
        return retryTest;
      case jobStatus.PENDING:
        return navigateToJob;
      case jobStatus.ACTIVE:
        return navigateToJob;
      case jobStatus.CANCELED:
        return navigateToJob;
      case jobStatus.QUEUED:
        return navigateToJob;
      default:
        return retryTest;
    }
  };

  function jobIcon() {
    if (pipeline && pipeline.isCanceled)
      return <DoNotDisturbIcon color="warning" />;
    if (pipeline) return <ViewColumnIcon color="secondary" />;
    if (!job) return <ReplayIcon />;
    switch (job.status) {
      case jobStatus.OK:
        return <CheckIcon color="success" />;
      case jobStatus.ERROR:
        return <ClearIcon color="error" />;
      case jobStatus.PENDING:
        return <PendingIcon color="info" />;
      case jobStatus.ACTIVE:
        return <VisibilityIcon color="primary" />;
      case jobStatus.CANCELED:
        return <DoNotDisturbIcon color="warning" />;
      case jobStatus.QUEUED:
        return <ViewColumnIcon color="secondary" />;
      default:
        return <ReplayIcon />;
    }
  }

  function Actions() {
    return (
      <React.Fragment>
        <a href={screenshotUrl}>
          <IconButton aria-label="photo" component="span">
            <PhotoCameraIcon />
          </IconButton>
        </a>

        <IconButton aria-label="retry" component="span" onClick={jobOnClick()}>
          {jobIcon()}
        </IconButton>

        <IconButton
          aria-label="silence"
          component="span"
          color={silencedUntil ? "primary" : "default"}
          onClick={silenceClick}
        >
          <NotificationsIcon />
        </IconButton>
        <IconButton
          color="error"
          aria-label="delete"
          component="span"
          onClick={removeClick}
        >
          <DeleteIcon />
        </IconButton>
      </React.Fragment>
    );
  }

  return (
    <Accordion
      expanded={open}
      onChange={toggleOpen}
      disableGutters={true}
      square
    >
      <AccordionSummary
        style={{
          backgroundColor: "rgba(0, 0, 0, .03)",
          flexWrap: "wrap",
        }}
      >
        <Badge
          sx={{ mr: 2 }}
          color={badgeColor()}
          badgeContent={dailyFails}
          anchorOrigin={{
            vertical: "top",
            horizontal: "left",
          }}
        ></Badge>
        <Badge
          sx={{ mr: 2 }}
          style={{ whiteSpace: "nowrap", left: "3.125rem" }}
          badgeContent={new Date(timestamp).toLocaleTimeString("en-US")}
          anchorOrigin={{
            vertical: "bottom",
            horizontal: "left",
          }}
        ></Badge>
        <Dialog
          open={removeOpen}
          onClose={handleRemoveClose()}
          sx={{ "& .MuiDialog-paper": { width: "80%", maxHeight: 435 } }}
          maxWidth="xs"
        >
          <DialogTitle>Remove failure?</DialogTitle>
          <DialogContent>
            <DialogContentText>
              This will remove 1 test from the database
            </DialogContentText>
          </DialogContent>
          <DialogActions>
            <Button onClick={handleRemoveClose()}>Cancel</Button>
            <Button onClick={handleRemoveClose(true)} autoFocus>
              Yes
            </Button>
          </DialogActions>
        </Dialog>

        <Typography component={"span"} style={{ wordBreak: "break-word" }}>
          {`${testClass}#`}
          <Box fontWeight="bold" display="inline">
            {testName}{" "}
          </Box>
          <br />
          <div>
            <span className="recent-results">
              {recentResults.map(
                (v, i) =>
                  (v && <CheckIcon key={i} color="success" />) || (
                    <ClearIcon key={i} color="error" />
                  )
              )}
            </span>
            {isPipeline && <ViewColumnIcon />}
          </div>
        </Typography>

        <Stack
          onClick={stopPropagation}
          sx={{ ml: "auto", display: { md: "none", lg: "none", xl: "none" } }}
        >
          <Actions />
        </Stack>
        <Stack
          onClick={stopPropagation}
          direction="row"
          sx={{
            ml: "auto",
            mb: "auto",
            mt: "auto",
            whiteSpace: "nowrap",
            display: { xs: "none", sm: "none", md: "block", lg: "block" },
          }}
        >
          <Actions />
        </Stack>
      </AccordionSummary>
      <AccordionDetails>
        <Typography component={"span"} style={{ wordBreak: "break-word" }}>
          {failedMessage}
        </Typography>
      </AccordionDetails>
    </Accordion>
  );
}
