import { getSession } from "~/sessions";
import { getMe } from "~/utils";
import { Link, useLoaderData, useTransition } from "@remix-run/react";
import { prisma } from "~/db.server";
import { Form } from "@remix-run/react";
import { json } from "@remix-run/node";
import { County } from "~/components/County";
import {
  AuthenticityTokenInput,
  useAuthenticityToken,
  verifyAuthenticityToken,
} from "remix-utils";
import { useState } from "react";

const countys = [
  "Ahvenanmaa",
  "Etelä-Karjala",
  "Etelä-Pohjanmaa",
  "Kainuu",
  "Kanta-Häme",
  "Keski-Pohjanmaa",
  "Keski-Suomi",
  "Kymenlaakso",
  "Lappi",
  "Pirkanmaa",
  "Pohjanmaa",
  "Pohjois-Karjala",
  "Pohjois-Pohjanmaa",
  "Pohjois-Savo",
  "Päijat-Häme",
  "Satakunta",
  "Uusimaa",
  "Varsinais-Suomi",
];

export async function action({ request }) {
  const session = await getSession(request.headers.get("Cookie"));
  try {
    await verifyAuthenticityToken(request, session);
  } catch {
    throw new Error("something went wrong");
  }

  const formData = await request.formData();
  const county = formData.get("county");

  if (!county || typeof county !== "string" || !countys.includes(county))
    throw new Error("bad county");

  if (!session.has("userId"))
    throw new Error("OAuth token not found in cookie");

  const me = await getMe(session.get("userId"));
  const selfData = await prisma.player.findUnique({
    where: {
      playerId: parseInt(me.id),
    },
  });

  if (selfData) {
    throw new Error("Already submitted");
  }

  const countySubmit = prisma.county.upsert({
    where: {
      name: county,
    },
    update: {
      players: {
        create: {
          playerId: parseInt(me.id),
          playerName: me.username,
          score: String(me.statistics.ranked_score),
          rank: me.statistics.global_rank
            ? parseInt(me.statistics.global_rank)
            : null,
          SSranks:
            parseInt(me.statistics.grade_counts.ss) +
            parseInt(me.statistics.grade_counts.ssh),
          Sranks:
            parseInt(me.statistics.grade_counts.s) +
            parseInt(me.statistics.grade_counts.sh),
          Aranks: parseInt(me.statistics.grade_counts.a),
        },
      },
    },
    create: {
      name: county,
      players: {
        create: {
          playerId: parseInt(me.id),
          playerName: me.username,
          score: String(me.statistics.ranked_score),
          rank: me.statistics.global_rank
            ? parseInt(me.statistics.global_rank)
            : null,
          SSranks:
            parseInt(me.statistics.grade_counts.ss) +
            parseInt(me.statistics.grade_counts.ssh),
          Sranks:
            parseInt(me.statistics.grade_counts.s) +
            parseInt(me.statistics.grade_counts.sh),
          Aranks: parseInt(me.statistics.grade_counts.a),
        },
      },
    },
  });

  return countySubmit;
}

export async function loader({ request }) {
  const url = new URL(request.url);
  const toSort = url.searchParams.get("toSort");
  const type = url.searchParams.get("type");

  const countyData = await prisma.county.findMany({
    include: {
      players: {
        orderBy: {
          [toSort ? toSort : "rank"]: type ? type : "asc",
        },
      },
    },
  });
  const session = await getSession(request.headers.get("Cookie"));
  if (!session.has("userId"))
    return json({
      countyData,
      linkParams: {
        id: process.env.OSU_CLIENT_ID,
        uri: process.env.OSU_REDIRECT_URI,
      },
    });

  const me = await getMe(session.get("userId"));

  const selfData = await prisma.player.findUnique({
    where: {
      playerId: parseInt(me.id),
    },
  });

  return json({ me, countyData, selfData });
}

export default function Index() {
  const [form, setForm] = useState();
  const data = useLoaderData();
  const transition = useTransition();

  return (
    <div className="flex min-h-screen flex-col">
      <header
        className="flex w-full flex-col items-center justify-between space-y-4 
      border-b border-ctp-surface0 bg-gradient-to-r from-ctp-crust to-ctp-mantle px-12 py-4 
      text-center shadow-lg md:flex-row md:space-y-0"
      >
        <div className="flex flex-col text-left">
          <h1 className="bg-gradient-to-r from-ctp-pink to-ctp-yellow bg-clip-text text-4xl font-light leading-none tracking-tighter text-transparent">
            Maakunta ranking
          </h1>
          <span className="text-left text-xs font-extralight leading-none tracking-tighter">
            made by Juunas
          </span>
        </div>
        {data.me ? (
          <div className="flex flex-col items-center justify-center">
            <img
              className="w-10 rounded-full outline"
              src={data.me.avatar_url}
              alt="me"
            />
            <h1>{data.me.username}</h1>
            {data.selfData ? (
              <Form
                onClick={() => setForm("us")}
                method="post"
                className="text-sky-400 hover:text-sky-600 hover:underline"
                action="/update"
              >
                <AuthenticityTokenInput />
                <button type="submit">
                  {transition.state === "submitting" && form === "us"
                    ? "Updating stats..."
                    : "Update stats"}
                </button>
              </Form>
            ) : (
              ""
            )}
            <Form
              onClick={() => setForm("lo")}
              method="post"
              className="text-sky-400 hover:text-sky-600 hover:underline"
              action="/logout"
            >
              <AuthenticityTokenInput />
              <button type="submit">
                {transition.state === "submitting" && form === "lo"
                  ? "Logging out..."
                  : "Logout"}
              </button>
            </Form>
          </div>
        ) : (
          <a
            href={`https://osu.ppy.sh/oauth/authorize?client_id=${
              data.linkParams.id
            }&redirect_uri=${
              data.linkParams.uri
            }&response_type=code&state=${useAuthenticityToken()}`}
            referrerPolicy="no-referrer"
            className="rounded-full border border-ctp-surface0 bg-ctp-surface0 px-4 py-2 shadow-md 
            shadow-ctp-overlay0 hover:bg-ctp-surface1 hover:shadow-ctp-overlay2"
          >
            Authenticate with osu! account
          </a>
        )}
      </header>
      {data?.me?.username ? (
        data.selfData ? (
          <h1 className="p-4 text-center font-bold">
            Kiitos, että osallistuit maakunta rankingiin!
          </h1>
        ) : (
          <Form
            className="flex flex-col items-center justify-center space-y-4 p-4 text-center"
            method="post"
          >
            <AuthenticityTokenInput />
            <label>
              <details>
                <summary className="cursor-pointer text-2xl font-semibold tracking-wide">
                  Valitse sinun tämän hetkinen maakunta
                </summary>
                <p className="text-sm">
                  Jos laitat vahingos väärän tai jotai nii pingaa juunas hyväs
                  mieles nii voin vaihtaa joo
                </p>
              </details>
            </label>
            <select
              className="rounded bg-ctp-surface2 p-2 shadow"
              name="county"
              id="county"
            >
              {countys.map((county, index) => (
                <option key={index} value={`${county}`}>
                  {county}
                </option>
              ))}
            </select>
            <button
              onClick={() => setForm("cs")}
              className="rounded-full border px-4 py-2 shadow shadow-ctp-overlay0 hover:shadow-xl"
              type="submit"
            >
              {transition.state === "submitting" && form === "cs"
                ? "Submitting..."
                : "Submit"}
            </button>
          </Form>
        )
      ) : (
        ""
      )}

      {data.countyData.length > 0 ? (
        <>
          <input
            className="peer/layout hidden w-fit"
            type="checkbox"
            name="layout"
            id="layout"
          />
          <label
            className="flex cursor-pointer justify-center pt-6 peer-checked/layout:text-ctp-green"
            htmlFor="layout"
          >
            Don't overflow
          </label>
          <ul
            className="flex flex-grow flex-col overflow-x-auto p-4 peer-checked/layout:flex-wrap 
        peer-checked/layout:justify-center md:flex-row"
          >
            {data.countyData.map((county) => (
              <County key={county.id} county={county} />
            ))}
          </ul>
        </>
      ) : (
        <h1 className="flex-grow p-6 text-center text-4xl">No data yet</h1>
      )}
    </div>
  );
}
