import Loading from "components/Loading";
import React, { useContext, useEffect, useMemo, useState } from "react";
import { useParams } from "react-router";
import styled from "styled-components";

import loading from "assets/loading.gif";
import { Drawer, withStyles } from "@material-ui/core";
import EventDrawer from "./EventDrawer";
import { useRouting } from "shared/routing";
import api from "shared/api";
import { Context } from "shared/Context";
import DynamicLink from "components/DynamicLink";
import Header from "components/expanded-object/Header";
import { capitalize } from "shared/string_utils";
import Description from "components/Description";
import { dateFormatter } from "../../chart/JobRunTable";

type IncidentPageParams = {
  incident_id: string;
};

const IncidentPage = () => {
  const { incident_id } = useParams<IncidentPageParams>();

  const { currentProject, currentCluster } = useContext(Context);

  const [incident, setIncident] = useState<Incident>(null);

  const [isRefreshing, setIsRefreshing] = useState(false);
  const [selectedEvent, setSelectedEvent] = useState<IncidentEvent>(null);

  const { getQueryParam, pushFiltered } = useRouting();

  useEffect(() => {
    let isSubscribed = true;

    setIncident(null);

    api
      .getIncidentById<Incident>(
        "<token>",
        { incident_id },
        {
          cluster_id: currentCluster.id,
          project_id: currentProject.id,
        }
      )
      .then((res) => {
        if (!isSubscribed) {
          return;
        }

        let incident = res.data;

        incident.events = convertEventsTimestampsToMilliseconds(
          incident.events
        );

        setIncident(incident);
      });

    return () => {
      isSubscribed = false;
    };
  }, [incident_id]);

  const refreshIncident = async () => {
    setIsRefreshing(true);
    try {
      let incident = await api
        .getIncidentById<Incident>(
          "<token>",
          { incident_id },
          {
            cluster_id: currentCluster.id,
            project_id: currentProject.id,
          }
        )
        .then((res) => res.data);

      incident.events = convertEventsTimestampsToMilliseconds(incident.events);

      setIncident(incident);
    } catch (error) {
    } finally {
      setIsRefreshing(false);
    }
  };

  const events = useMemo(() => {
    return groupEventsByDate(incident?.events);
  }, [incident]);

  if (incident === null) {
    return <Loading />;
  }

  const getBackLink = () => {
    return (
      getQueryParam("redirect_url") ||
      "/cluster-dashboard?selected_tab=incidents"
    );
  };

  const getResourceLink = () => {
    let chartName = incident?.chart_name.split("-")[0] || "web";
    let namespace = incident?.incident_id.split(":")[2] || "default";

    if (chartName == "job") {
      return `/jobs/${currentCluster.name}/${namespace}/${incident?.release_name}`;
    }

    return `/applications/${currentCluster.name}/${namespace}/${incident?.release_name}`;
  };

  return (
    <StyledExpandedNodeView>
      <HeaderWrapper>
        <Header
          last_updated={dateFormatter(incident.updated_at * 1000)}
          back_link={getBackLink()}
          name={"Incident for " + incident.release_name}
          icon={"error"}
          materialIconClass="material-icons"
          inline_title_items={[
            <ResourceLink
              key="resource_link"
              to={getResourceLink()}
              target="_blank"
              onClick={(e) => e.stopPropagation()}
            >
              {incident.release_name}
              <i className="material-icons">open_in_new</i>
            </ResourceLink>,
          ]}
          sub_title_items={[
            <StatusContainer>
              <Status>
                <StatusDot status={incident.latest_state} />
                {capitalize(incident.latest_state)}
              </Status>
              <StatusText>
                - started {dateFormatter(incident.created_at * 1000)}, last
                updated {dateFormatter(incident.updated_at * 1000)}
              </StatusText>
              <Description></Description>
            </StatusContainer>,
          ]}
        />
      </HeaderWrapper>
      <LineBreak />
      <BodyWrapper>
        <RefreshButton onClick={refreshIncident} disabled={isRefreshing}>
          {isRefreshing ? (
            <>
              <img src={loading} alt="loading icon" />
            </>
          ) : (
            <i className="material-icons">refresh</i>
          )}
        </RefreshButton>
        {Object.entries(events).map(([date, events_list]) => (
          <React.Fragment key={date}>
            <StyledDate>{date}</StyledDate>

            {events_list.map((event) => {
              return (
                <StyledCard
                  key={event.event_id}
                  onClick={() => setSelectedEvent(event)}
                  active={selectedEvent?.event_id === event.event_id}
                >
                  <ContentContainer>
                    <Icon status={"normal"} className="material-icons-outlined">
                      info
                    </Icon>
                    <EventInformation>
                      <EventName>
                        <Helper>Pod:</Helper>
                        {event.pod_name}
                      </EventName>
                      <EventReason>{event.message}</EventReason>
                    </EventInformation>
                  </ContentContainer>
                  <ActionContainer>
                    <TimestampContainer>
                      <TimestampIcon className="material-icons-outlined">
                        access_time
                      </TimestampIcon>
                      <span>
                        {Intl.DateTimeFormat([], {
                          // @ts-ignore
                          dateStyle: "full",
                          timeStyle: "long",
                        }).format(new Date(event.timestamp))}
                      </span>
                    </TimestampContainer>
                  </ActionContainer>
                </StyledCard>
              );
            })}
          </React.Fragment>
        ))}
      </BodyWrapper>
      <StyledDrawer
        anchor="right"
        open={!!selectedEvent}
        onClose={() => setSelectedEvent(null)}
      >
        <EventDrawer
          event={selectedEvent}
          closeDrawer={() => setSelectedEvent(null)}
        />
      </StyledDrawer>
    </StyledExpandedNodeView>
  );
};

export default IncidentPage;

const convertEventsTimestampsToMilliseconds = (events: IncidentEvent[]) => {
  return events.map((e) => {
    let newEvent = e;

    newEvent.timestamp = newEvent.timestamp * 1000;

    return newEvent;
  });
};

const groupEventsByDate = (
  events: IncidentEvent[]
): { [key: string]: IncidentEvent[] } => {
  if (!events?.length) {
    return {};
  }

  return events.reduce<{ [key: string]: IncidentEvent[] }>(
    (accumulator, current) => {
      // @ts-ignore
      const date = Intl.DateTimeFormat([], { dateStyle: "full" }).format(
        new Date(current.timestamp)
      );

      if (accumulator[date]?.length) {
        accumulator[date].push(current);
      } else {
        accumulator[date] = [current];
      }

      return accumulator;
    },
    {}
  );
};

export type IncidentContainerEvent = {
  container_name: string;
  reason: string;
  message: string;
  exit_code: number;
  log_id: string;
};

export type IncidentEvent = {
  event_id: string;
  pod_name: string;
  cluster: string;
  namespace: string;
  release_name: string;
  release_type: string;
  timestamp: number;
  pod_phase: string;
  pod_status: string;
  reason: string;
  message: string;
  container_events: {
    [key: string]: IncidentContainerEvent;
  };
};

export type Incident = {
  incident_id: string;
  release_name: string; // eg: "sample-web"
  latest_state: string; // "ONGOING" or "RESOLVED"
  latest_reason: string; // eg: "Out of memory",
  latest_message: string; // eg: "Application crash due to out of memory issue"
  events: IncidentEvent[];
  created_at: number;
  updated_at: number;
  chart_name: string;
};

const RefreshButton = styled.button`
  position: absolute;
  right: 0px;
  top: 20px;
  border: 1px solid #ffffff00;
  border-radius: 50%;
  background: inherit;
  color: #ffffff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 35px;
  height: 35px;

  > i {
    font-size: 20px;
  }
  > img {
    width: 20px;
    height: 20px;
  }

  :hover {
    color: #ffffff88;
    border-color: #ffffff88;
  }
`;

const LineBreak = styled.div`
  width: calc(100% - 0px);
  height: 2px;
  background: #ffffff20;
  margin: 10px 0px 35px;
`;

const BodyWrapper = styled.div`
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
`;

const HeaderWrapper = styled.div`
  position: relative;
`;

const StyledExpandedNodeView = styled.div`
  width: 100%;
  z-index: 0;
  animation: fadeIn 0.3s;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
  display: flex;
  overflow-y: auto;
  padding-bottom: 120px;
  flex-direction: column;
  overflow: visible;

  @keyframes fadeIn {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
`;

const StyledDate = styled.div`
  font-size: 18px;
  font-weight: bold;
  color: #ffffff;
  margin-bottom: 20px;
  margin-top: 20px;
  :first-child {
    margin-top: 0px;
  }
`;

const StyledCard = styled.div<{ active: boolean }>`
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 1px solid ${({ active }) => (active ? "#819bfd" : "#ffffff44")};
  background: #ffffff08;
  margin-bottom: 5px;
  border-radius: 10px;
  padding: 14px;
  overflow: hidden;
  height: 80px;
  font-size: 13px;
  cursor: pointer;
  :hover {
    background: #ffffff11;
    border: 1px solid ${({ active }) => (active ? "#819bfd" : "#ffffff66")};
  }
  animation: fadeIn 0.5s;
  @keyframes fadeIn {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
  :not(:last-child) {
    margin-bottom: 15px;
  }
`;

const ContentContainer = styled.div`
  display: flex;
  height: 100%;
  width: 100%;
  align-items: center;
`;

const Icon = styled.span<{ status: "critical" | "normal" }>`
  font-size: 20px;
  margin-left: 10px;
  margin-right: 20px;
  color: ${({ status }) => (status === "critical" ? "#ff385d" : "#aaaabb")};
`;

const EventInformation = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  height: 100%;
`;

const EventName = styled.div`
  font-family: "Work Sans", sans-serif;
  font-weight: 500;
  color: #ffffff;
`;

const Helper = styled.span`
  text-transform: capitalize;
  color: #ffffff44;
  margin-right: 5px;
`;

const EventReason = styled.div`
  font-family: "Work Sans", sans-serif;
  color: #aaaabb;
  margin-top: 5px;
`;

const ActionContainer = styled.div`
  display: flex;
  align-items: center;
  white-space: nowrap;
  height: 100%;
`;

const TimestampContainer = styled.div`
  display: flex;
  white-space: nowrap;
  align-items: center;
  justify-self: flex-end;
  color: #ffffff55;
  margin-right: 10px;
  font-size: 13px;
  min-width: 130px;
  justify-content: space-between;
`;

const TimestampIcon = styled.span`
  margin-right: 7px;
  font-size: 18px;
`;

const StyledDrawer = withStyles({
  paperAnchorRight: {
    background: "#202227",
    minWidth: "700px",
  },
})(Drawer);

const ResourceLink = styled(DynamicLink)`
  font-size: 13px;
  font-weight: 400;
  margin-left: 20px;
  color: #aaaabb;
  display: flex;
  align-items: center;

  :hover {
    text-decoration: underline;
    color: white;
  }

  > i {
    margin-left: 7px;
    font-size: 17px;
  }
`;

const Status = styled.span`
  font-size: 13px;
  display: flex;
  align-items: center;
  margin-left: 1px;
  min-height: 17px;
  color: #a7a6bb;
  margin-right: 6px;
`;

const StatusDot = styled.div`
  width: 8px;
  height: 8px;
  background: ${(props: { status: string }) =>
    props.status === "ONGOING" ? "#ed5f85" : "#4797ff"};
  border-radius: 20px;
  margin-left: 3px;
  margin-right: 15px;
`;

const StatusContainer = styled.div`
  display: flex;
  align-items: center;
  font-size: 13px;
  color: #aaaabb;
  width: 100%;
`;

const StatusText = styled.div`
  width: 100%;
`;
