import calendarStyles from "react-big-calendar/lib/css/react-big-calendar.css";
import eventStyles from "../styles/events-team.css";
import { Calendar, dayjsLocalizer } from "react-big-calendar";
import dayjs from "dayjs";
import { type LinksFunction } from "@remix-run/cloudflare";
import {
  Accordion,
  AccordionButton,
  AccordionIcon,
  AccordionItem,
  AccordionPanel,
  Box,
  Button,
  Container,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  useDisclosure,
} from "@chakra-ui/react";
import { useLoaderData } from "@remix-run/react";
import { useState } from "react";
import utc from "dayjs/plugin/utc.js";

export const links: LinksFunction = () => {
  return [
    { href: calendarStyles, rel: "stylesheet" },
    { href: eventStyles, rel: "stylesheet" },
  ];
};

export async function loader({ context }: { context: RequestContext }) {
  if (!context.data.current_user)
    throw new Response(null, {
      status: 401,
    });

  if (
    ![1 << 3, 1 << 4, 1 << 12].find(
      (p) => context.data.current_user.permissions & p,
    )
  )
    throw new Response(null, {
      status: 403,
    });

  const now = new Date();
  const eventsData = await context.env.D1.prepare(
    "SELECT answer, approved, created_by, day, details, id, month, pending, performed_at, reached_minimum_player_count, type, year FROM events WHERE month = ? AND year = ? ORDER BY day;",
  )
    .bind(now.getUTCMonth() + 1, now.getUTCFullYear())
    .all();

  if (eventsData.error)
    throw new Response(null, {
      status: 500,
    });

  const calendarData = eventsData.results.map((e) => {
    return {
      id: e.id,
      title: (e.type as string).toUpperCase(),
      allDay: true,
      // A Date object will not survive being passed to the client
      start: `${e.year}-${(e.month as number).toString().padStart(2, "0")}-${(e.day as number).toString().padStart(2, "0")}T00:00:00.000Z`,
      end: `${e.year}-${(e.month as number).toString().padStart(2, "0")}-${(e.day as number).toString().padStart(2, "0")}T00:00:00.000Z`,
    };
  });

  const memberData = await context.env.D1.prepare(
    "SELECT id, name FROM et_members WHERE id IN (SELECT created_by FROM events WHERE month = ? AND year = ?);",
  )
    .bind(now.getUTCMonth() + 1, now.getUTCFullYear())
    .all();

  return {
    calendarData,
    eventList: eventsData.results,
    memberData: memberData.results,
  };
}

export default function () {
  const data = useLoaderData<typeof loader>();
  const [selectedDate, setDate] = useState(new Date());
  const [eventData, setEventData] = useState({} as { [k: string]: any });
  const { isOpen, onClose, onOpen } = useDisclosure();
  const getEventsOfDay = (date: Date) =>
    data.eventList.filter(
      (e) =>
        e.day === date.getUTCDate() &&
        e.month === date.getUTCMonth() + 1 &&
        e.year === date.getUTCFullYear(),
    ) as { [k: string]: any }[];
  const [eventsOfDay, setEventsOfDay] = useState(getEventsOfDay(selectedDate));

  dayjs.extend(utc);

  return (
    <Container maxW="container.lg" h="600px">
      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Event Info</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            Host:{" "}
            {
              (
                data.memberData.find((m) => m.id === eventData.created_by) as {
                  [k: string]: any;
                }
              )?.name
            }
            <br />
            Event Type: {eventData?.type?.toUpperCase()}
            <br />
            Details: {eventData?.details}
            <br />
            Answer: {eventData?.type === "rotw" ? eventData.answer : "N/A"}
          </ModalBody>
          <ModalFooter>
            <Button onClick={onClose}>Close</Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
      <Calendar
        endAccessor={(event) => new Date(event.end)}
        events={data.calendarData}
        localizer={dayjsLocalizer(dayjs)}
        onSelectEvent={(e) => {
          setEventData(
            data.eventList.find((ev) => ev.id === e.id) as { [k: string]: any },
          );
          onOpen();
        }}
        onSelectSlot={(s) => {
          const date = s.slots.at(0) as Date;
          setDate(date);
          setEventsOfDay(getEventsOfDay(date));
        }}
        popup
        startAccessor={(event) => new Date(event.start)}
        style={{ height: 500 }}
        views={{
          month: true,
          week: false,
          work_week: false,
          day: false,
          agenda: false,
        }}
      />
      <Accordion id="events-accordion" mt="16px">
        <AccordionItem>
          <h2>
            <AccordionButton>
              <Box as="span" flex="1" textAlign="left">
                Fact of the Day
              </Box>
              <AccordionIcon />
            </AccordionButton>
          </h2>
          <AccordionPanel pb={4}>
            {eventsOfDay.find((e) => e.type === "fotd")?.details || "None"}
            <br />
          </AccordionPanel>
        </AccordionItem>
        <AccordionItem>
          <h2>
            <AccordionButton>
              <Box as="span" flex="1" textAlign="left">
                Gamenight
              </Box>
              <AccordionIcon />
            </AccordionButton>
          </h2>
          <AccordionPanel pb={4}>
            {eventsOfDay.find((e) => e.type === "gamenight")?.details || "None"}
          </AccordionPanel>
        </AccordionItem>
        <AccordionItem>
          <h2>
            <AccordionButton>
              <Box as="span" flex="1" textAlign="left">
                Riddle of the Week
              </Box>
            </AccordionButton>
          </h2>
          <AccordionPanel pb={4}>
            {eventsOfDay.find((e) => e.type === "rotw")?.details || "None"}
          </AccordionPanel>
        </AccordionItem>
        <AccordionItem>
          <h2>
            <AccordionButton>
              <Box as="span" flex="1" textAlign="left">
                Question of the Day
              </Box>
            </AccordionButton>
          </h2>
          <AccordionPanel pb={4}>
            {eventsOfDay.find((e) => e.type === "qotd")?.details || "None"}
          </AccordionPanel>
        </AccordionItem>
      </Accordion>
    </Container>
  );
}
