import {
  Container,
  Heading,
  Table,
  TableCaption,
  TableContainer,
  Tbody,
  Td,
  Th,
  Thead,
  Tr,
} from "@chakra-ui/react";
import { useLoaderData } from "@remix-run/react";

export async function loader({ context }: { context: RequestContext }) {
  const { current_user: user } = context.data;

  if (!user)
    throw new Response(null, {
      status: 401,
    });

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

  const now = new Date();
  let month = now.getUTCMonth();
  let year = now.getUTCFullYear();

  if (month === 0) {
    year--;
    month = 12;
  }

  const eventMemberQuery = await context.env.D1.prepare(
    "SELECT id, name, roblox_id FROM et_members;",
  ).all();
  const inactivityQuery: D1Result<Record<string, any>> =
    await context.env.D1.prepare(
      "SELECT decisions, json_extract(user, '$.id') AS uid FROM inactivity_notices WHERE (end BETWEEN DATE('now', 'start of month', '-1 month') AND DATE('now', 'start of month', '-1 day')) OR (start BETWEEN DATE('now', 'start of month', '-1 month') AND DATE('now', 'start of month', '-1 day'));",
    ).all();

  const eventsQuery = await context.env.D1.prepare(
    "SELECT approved, answered_at, created_by, performed_at, reached_minimum_player_count, type FROM events WHERE month = ? AND year = ?;",
  )
    .bind(month, year)
    .all();
  const memberMap = Object.fromEntries(
    eventMemberQuery.results.map((entry) => {
      return [
        entry.id,
        { name: entry.name, points: 0, roblox_id: entry.roblox_id },
      ];
    }),
  );

  for (const event of eventsQuery.results as {
    approved: number;
    answered_at: number;
    created_by: string;
    performed_at: number;
    reached_minimum_player_count: number;
    type: string;
  }[]) {
    if (!memberMap[event.created_by] || !event.approved) continue;

    if (event.performed_at) memberMap[event.created_by].points += 10;
    else memberMap[event.created_by].points -= 5;

    if (event.type === "gamenight" && event.reached_minimum_player_count)
      memberMap[event.created_by].points += 10;
  }

  for (const member of Object.keys(memberMap))
    if (
      memberMap[member].points < 30 &&
      !inactivityQuery.results.find(
        (i) => i.uid === member && JSON.parse(i.decisions).et,
      )
    )
      memberMap[member].points -= 30;

  return {
    members: memberMap,
  };
}

export default function () {
  const data = useLoaderData<typeof loader>() as {
    members: {
      [k: string]: { name: string; points: number; roblox_id?: number };
    };
  };
  const now = new Date();
  let month = now.getUTCMonth();
  let year = now.getUTCFullYear();

  if (month === 0) {
    month = 12;
    year--;
  }

  return (
    <Container maxW="container.lg">
      <Heading>
        Report for {month}/{year}
      </Heading>
      <TableContainer mt="16px">
        <Table variant="simple">
          <TableCaption>
            Total points earned for the previous month
          </TableCaption>
          <Thead>
            <Tr>
              <Th>ID</Th>
              <Th>Name</Th>
              <Th>Points</Th>
              <Th>Roblox ID</Th>
            </Tr>
          </Thead>
          <Tbody>
            {Object.entries(data.members).map(([key, value]) => (
              <Tr>
                <Td>{key}</Td>
                <Td>{value.name}</Td>
                <Td>{value.points}</Td>
                <Td>{value.roblox_id}</Td>
              </Tr>
            ))}
          </Tbody>
        </Table>
      </TableContainer>
    </Container>
  );
}