import Layout from "@/components/High/Layout";
import TicketDisplay from "@/components/High/TicketDisplay";
import Select from "@/components/Low/Select";
import Modal from "@/components/Modal";
import useTickets from "@/hooks/useTickets";
import useUser from "@/hooks/useUser";
import useUsers from "@/hooks/useUsers";
import {
  Ticket,
  TicketStatus,
  TicketStatusLabel,
  TicketType,
  TicketTypeLabel,
} from "@/interfaces/ticket";
import { sessionOptions } from "@/lib/session";
import { shouldRedirectHome } from "@/utils/navigation.disabled";
import {
  createColumnHelper,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from "@tanstack/react-table";
import clsx from "clsx";
import { withIronSessionSsr } from "iron-session/next";
import moment from "moment";
import Head from "next/head";
import { useEffect, useState } from "react";
import { ToastContainer } from "react-toastify";

const columnHelper = createColumnHelper<Ticket>();

export const getServerSideProps = withIronSessionSsr(({ req, res }) => {
  const user = req.session.user;

  if (!user || !user.isVerified) {
    res.setHeader("location", "/login");
    res.statusCode = 302;
    res.end();
    return {
      props: {
        user: null,
      },
    };
  }

  if (shouldRedirectHome(user) || user.type !== "developer") {
    res.setHeader("location", "/");
    res.statusCode = 302;
    res.end();
    return {
      props: {
        user: null,
      },
    };
  }

  return {
    props: { user: req.session.user },
  };
}, sessionOptions);

const StatusClassNames: { [key in TicketStatus]: string } = {
  submitted: "bg-mti-gray-dim",
  "in-progress": "bg-mti-blue-dark",
  completed: "bg-mti-green-dark",
};

const TypesClassNames: { [key in TicketType]: string } = {
  feedback: "bg-mti-green-light",
  bug: "bg-mti-red-dark",
  help: "bg-mti-blue-light",
};

export default function Tickets() {
  const [filteredTickets, setFilteredTickets] = useState<Ticket[]>([]);
  const [selectedTicket, setSelectedTicket] = useState<Ticket>();
  const [assigneeFilter, setAssigneeFilter] = useState<string>();

  const [typeFilter, setTypeFilter] = useState<TicketType>();
  const [statusFilter, setStatusFilter] = useState<TicketStatus>();

  const { user } = useUser({ redirectTo: "/login" });
  const { users } = useUsers();
  const { tickets, reload } = useTickets();

  useEffect(() => {
    const filters = [];
    if (typeFilter) filters.push((x: Ticket) => x.type === typeFilter);
    if (statusFilter) filters.push((x: Ticket) => x.status === statusFilter);
    if (assigneeFilter)
      filters.push((x: Ticket) => x.assignedTo === assigneeFilter);

    setFilteredTickets(filters.reduce((d, f) => d.filter(f), tickets));
  }, [tickets, typeFilter, statusFilter, assigneeFilter]);

  const columns = [
    columnHelper.accessor("id", {
      header: "ID",
      cell: (info) => info.getValue(),
    }),
    columnHelper.accessor("type", {
      header: "Type",
      cell: (info) => (
        <span
          className={clsx(
            "rounded-lg p-1 px-2 text-white",
            TypesClassNames[info.getValue()],
          )}
        >
          {TicketTypeLabel[info.getValue()]}
        </span>
      ),
    }),
    columnHelper.accessor("reporter", {
      header: "Reporter",
      cell: (info) => info.getValue().email,
    }),
    columnHelper.accessor("reportedFrom", {
      header: "Reported From",
      cell: (info) => info.getValue(),
    }),
    columnHelper.accessor("date", {
      header: "Date",
      cell: (info) => moment(info.getValue()).format("DD/MM/YYYY - HH:mm"),
    }),
    columnHelper.accessor("subject", {
      header: "Subject",
      cell: (info) =>
        info.getValue().substring(0, 12) +
        (info.getValue().length > 12 ? "..." : ""),
    }),
    columnHelper.accessor("status", {
      header: "Status",
      cell: (info) => (
        <span
          className={clsx(
            "rounded-lg p-1 px-2 text-white",
            StatusClassNames[info.getValue()],
          )}
        >
          {TicketStatusLabel[info.getValue()]}
        </span>
      ),
    }),
    columnHelper.accessor("assignedTo", {
      header: "Assignee",
      cell: (info) => users.find((x) => x.id === info.getValue())?.name || "",
    }),
  ];

  const table = useReactTable({
    data: filteredTickets,
    columns: columns,
    getCoreRowModel: getCoreRowModel(),
  });

  return (
    <>
      <Modal
        isOpen={!!selectedTicket}
        onClose={() => {
          reload();
          setSelectedTicket(undefined);
        }}
      >
        {selectedTicket && (
          <TicketDisplay
            user={user!}
            ticket={selectedTicket}
            onClose={() => {
              reload();
              setSelectedTicket(undefined);
            }}
          />
        )}
      </Modal>

      <Head>
        <title>Tickets Panel | EnCoach</title>
        <meta
          name="description"
          content="A training platform for the IELTS exam provided by the Muscat Training Institute and developed by eCrop."
        />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <ToastContainer />
      {user && (
        <Layout user={user} className="gap-6">
          <h1 className="text-2xl font-semibold">Tickets</h1>

          <div className="flex w-full items-center gap-4">
            <div className="flex w-full flex-col gap-3">
              <label className="text-mti-gray-dim text-base font-normal">
                Status
              </label>
              <Select
                options={Object.keys(TicketStatusLabel).map((x) => ({
                  value: x,
                  label: TicketStatusLabel[x as keyof typeof TicketStatusLabel],
                }))}
                value={
                  statusFilter
                    ? {
                        value: statusFilter,
                        label: TicketStatusLabel[statusFilter],
                      }
                    : undefined
                }
                onChange={(value) =>
                  setStatusFilter((value?.value as TicketStatus) ?? undefined)
                }
                isClearable
                placeholder="Status..."
              />
            </div>
            <div className="flex w-full flex-col gap-3">
              <label className="text-mti-gray-dim text-base font-normal">
                Type
              </label>
              <Select
                options={Object.keys(TicketTypeLabel).map((x) => ({
                  value: x,
                  label: TicketTypeLabel[x as keyof typeof TicketTypeLabel],
                }))}
                value={
                  typeFilter
                    ? { value: typeFilter, label: TicketTypeLabel[typeFilter] }
                    : undefined
                }
                onChange={(value) =>
                  setTypeFilter((value?.value as TicketType) ?? undefined)
                }
                isClearable
                placeholder="Type..."
              />
            </div>
            <div className="flex w-full flex-col gap-3">
              <label className="text-mti-gray-dim text-base font-normal">
                Assignee
              </label>
              <Select
                options={[
                  { value: "me", label: "Assigned to me" },
                  ...users
                    .filter((x) => ["admin", "developer"].includes(x.type))
                    .map((u) => ({
                      value: u.id,
                      label: `${u.name} - ${u.email}`,
                    })),
                ]}
                value={
                  assigneeFilter
                    ? {
                        value: assigneeFilter,
                        label: `${users.find((u) => u.id === assigneeFilter)?.name} - ${users.find((u) => u.id === assigneeFilter)?.email}`,
                      }
                    : null
                }
                onChange={(value) =>
                  value
                    ? setAssigneeFilter(
                        value.value === "me" ? user.id : value.value,
                      )
                    : setAssigneeFilter(undefined)
                }
                placeholder="Assignee..."
                isClearable
              />
            </div>
          </div>

          <table className="bg-mti-purple-ultralight/40 w-full rounded-xl">
            <thead>
              {table.getHeaderGroups().map((headerGroup) => (
                <tr key={headerGroup.id}>
                  {headerGroup.headers.map((header) => (
                    <th className="px-4 py-4 text-left" key={header.id}>
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext(),
                          )}
                    </th>
                  ))}
                </tr>
              ))}
            </thead>
            <tbody className="px-2">
              {table.getRowModel().rows.map((row) => (
                <tr
                  className={clsx(
                    "even:bg-mti-purple-ultralight/40 hover:bg-mti-purple-ultralight cursor-pointer rounded-lg py-2 odd:bg-white",
                    "transition duration-300 ease-in-out",
                  )}
                  onClick={() => setSelectedTicket(row.original)}
                  key={row.id}
                >
                  {row.getVisibleCells().map((cell) => (
                    <td className="w-fit items-center px-4 py-2" key={cell.id}>
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext(),
                      )}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </Layout>
      )}
    </>
  );
}
