import React, { useState } from "react";
import { Button, ListGroup, Collapse } from "react-bootstrap";
import {
  Dash,
  ChevronDown,
  ChevronRight,
  CircleFill,
} from "react-bootstrap-icons";
import { Container, Row, Col, Table, Card } from "react-bootstrap";
import { atom, useAtomValue } from "jotai";
import { atomWithQuery } from "jotai-tanstack-query";

const diagQueryFn = async () => {
  const resp = await fetch("api/diagnostics");
  if (!resp.ok) {
    throw new Error("Network response was not ok");
  }
  return resp.json();
};

const diagQueryAtom = atomWithQuery(() => ({
  queryKey: ["diagnostics"],
  queryFn: diagQueryFn,
}));

const diagAtom = atom((get) => {
  const diag = get(diagQueryAtom);
  if (diag.isPending) {
    return "Loading...";
  }
  if (diag.isError) {
    return "Error loading!";
  }
  if (!diag.data.status) {
    return "Failed to get diagnostic information.";
  }
  return diag.data.message;
});

export function DiagnosticsCard() {
  const diagnostics = useAtomValue(diagAtom);

  const diagContent = () => {
    if (typeof diagnostics === "string" || diagnostics instanceof String) {
      return <pre> {diagnostics} </pre>;
    }
    return <TreeView data={diagnostics} />;
  };

  return (
    <Card className="padded">
      <Card.Title>Diagnostics</Card.Title>
      <Card.Body>{diagContent()}</Card.Body>
    </Card>
  );
}

function TreeView(props: Any) {
  const data = props.data;
  return (
    <ListGroup>
      {data.children.map((node) => (
        <SingleNode key={node.id} node={node} />
      ))}
    </ListGroup>
  );
}

function LevelIndicator(props: Any) {
  const level = props.level;
  if (level == "ERROR") {
    return <CircleFill color="red" />;
  }
  if (level == "WARN") {
    return <CircleFill color="orange" />;
  }
  if (level == "OK") {
    return <CircleFill color="green" />;
  }
  return <CircleFill color="grey" />;
}

function MessageText(props: Any) {
  if (props.message === "") {
    return <div></div>;
  }
  return <div>Message: {props.message}</div>;
}

function ValuesTable(props: Any) {
  const values = props.values;
  if (Object.keys(values).length === 0) {
    return <div></div>;
  }
  return (
    <Table>
      <thead>
        <th>Key</th>
        <th>Value</th>
      </thead>
      <tbody>
        {Object.entries(values).map(([key, value]) => (
          <tr key={key}>
            <td>{key}</td>
            <td>{value}</td>
          </tr>
        ))}
      </tbody>
    </Table>
  );
}

function StatusContent(props: Any) {
  const status = props.status;
  console.log(status);
  return (
    <div>
      <p>{status.name}</p>
      <p>
        <MessageText message={status.message} />
      </p>
      <p>
        <ValuesTable values={status.values} />
      </p>
    </div>
  );
}

function DirectionIcon(props: Any) {
  let icon = <ChevronRight />;
  if (props.isOpen) {
    icon = <ChevronDown />;
  }
  if (!props.hasChildren) {
    icon = <Dash />;
  }

  return (
    <Button variant="link" onClick={props.onClick}>
      {icon}
    </Button>
  );
}

function ChildStatuses(props: Any) {
  const isOpen = props.isOpen;
  const node = props.node;
  return (
    <Collapse in={isOpen}>
      <div>
        <ListGroup>
          {node.children.map((child) => (
            <SingleNode key={child.id} node={child} />
          ))}
        </ListGroup>
      </div>
    </Collapse>
  );
}

function SingleNode(props: Any) {
  const node = props.node;

  const [isOpen, setIsOpen] = useState(false);
  const hasChildren = node.children && node.children.length > 0;
  const openFunction = () => {
    if (hasChildren) {
      setIsOpen(!isOpen);
    }
  };

  return (
    <ListGroup.Item>
      <Container>
        <Row>
          <Col xs={1}>
            <DirectionIcon
              isOpen={isOpen}
              hasChildren={hasChildren}
              onClick={openFunction}
            />
          </Col>
          <Col xs={1}>
            <LevelIndicator level={node.status.level} />
          </Col>
          <Col xs={"auto"}>
            <StatusContent status={node.status} />
          </Col>
        </Row>
        <Row>
          <ChildStatuses isOpen={isOpen} node={node} />
        </Row>
      </Container>
    </ListGroup.Item>
  );
}
