import {
  Button,
  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 batchStatements: D1Result<Record<string, any>>[] =
    await context.env.D1.batch([
      context.env.D1.prepare("SELECT id, name, roblox_id FROM et_members;"),
      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'));",
      ),
      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),
    ]);

  const memberMap = Object.fromEntries(
    batchStatements[0].results.map((e) => {
      return [e.id, { name: e.name, points: 0, roblox_id: e.roblox_id }];
    }),
  );

  for (const event of batchStatements[2].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 < 50 ||
        batchStatements[2].results.filter(
          (e) => e.type === "gamenight" && e.created_by === member,
        ).length === 0) &&
      !batchStatements[1].results.find(
        (i) => i.uid === member && JSON.parse(i.decisions).et,
      )
    )
      memberMap[member].points -= 50;

  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>
      <Button
        colorScheme="blue"
        my="16px"
        onClick={async () => {
          await navigator.clipboard.writeText(
            `local Report = {
  ${Object.values(data.members)
    .map((v) => `[${v.roblox_id}] = ${v.points};`)
    .join("\n  ")}
}`,
          );

          alert("Report copied.");
        }}
      >
        Copy Report
      </Button>
    </Container>
  );
}
