import { m, Variants } from "framer-motion";
import Link from "next/link";
import { ReactElement, useEffect, useState } from "react";
import Loading from "../../components/common/Loading";
import UserJSONEntry from "../../interfaces/UserJSONEntry";
import DashLayout from "../../layouts/DashLayout";

function Ranking() {
  const [sortBy, setSortBy] = useState("netWorth");
  const [sortAsc, setSortAsc] = useState(false);
  const [fakeData, setFakeData] = useState([]);
  const [dataLoaded, setDataLoaded] = useState(false);

  useEffect(() => {
    setDataLoaded(false);
    // fetch data from api on change to sort method
    fetch(`/api/fakeUsers?s=${sortBy}&a=${sortAsc}`)
      .then((res) => res.json())
      .then((data) => {
        setFakeData(data.data);
        setDataLoaded(true);
      });
  }, [sortBy, sortAsc]);

  const SortSVG = (props: { sortType: string; children?: ReactElement }) => {
    // if not current sort, return a line, otherwise return an arrow corresponding to sortAsc
    if (sortBy != props.sortType) {
      return (
        <m.svg
          className="ml-2 h-[12px] w-[12px] md:h-[15px] md:w-[15px] "
          origin="center"
          viewBox="0 0 6 6"
        >
          <m.line
            x1="1"
            y1="3"
            x2="5"
            y2="3"
            stroke="white"
            strokeLinecap="round"
          />
        </m.svg>
      );
    }
    return (
      <m.svg
        className="ml-2 h-[12px] w-[12px] sm:h-[15px] sm:w-[15px]"
        origin="center"
        viewBox="0 0 330 330"
        // if asc, rotate 180
        transform={sortAsc ? "rotate(180)" : ""}
      >
        <m.path
          d="M325.607,79.393c-5.857-5.857-15.355-5.858-21.213,0.001l-139.39,139.393L25.607,79.393  c-5.857-5.857-15.355-5.858-21.213,0.001c-5.858,5.858-5.858,15.355,0,21.213l150.004,150c2.813,2.813,6.628,4.393,10.606,4.393  s7.794-1.581,10.606-4.394l149.996-150C331.465,94.749,331.465,85.251,325.607,79.393z"
          fill="white"
          stroke="white"
          strokeWidth="15"
          strokeLinecap="round"
        />
      </m.svg>
    );
  };

  const setSortMethod = (sortType: string) => {
    // if same sort, toggle asc
    // a change in sort means asc should be false for intuitive behavior
    if (sortBy == sortType) {
      setSortAsc(!sortAsc);
    } else {
      setSortAsc(false);
      setSortBy(sortType);
    }
  };

  return (
    <>
      <div className="flex w-full justify-center">
        <div className="ml-3 flex w-full max-w-7xl flex-col items-center justify-start font-plusJakarta font-semibold lg:ml-0">
          {/* hidden if smaller than lg */}
          <m.h1
            className="hidden py-10 text-center text-5xl font-normal text-pink-300 lg:block lg:text-6xl"
            variants={headerVariants}
          >
            top investors
          </m.h1>
          {/* TODO: responsive for extremely skinny displays (i.e. galaxy fold), or really for mobile entirely so info is not lost */}
          <m.div
            className="inline-grid w-full rounded-t-2xl bg-zinc-800 bg-opacity-70 p-3 pt-4 text-sm sm:text-xl"
            initial="initial"
            animate="animate"
            exit="exit"
            variants={rankingCardVariants}
          >
            {/* Column names and arrows */}
            <div className="inline-grid w-full grid-flow-col grid-cols-[0.75fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-400 px-5 pb-3 text-right text-gray-300 md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]">
              <h1 className="text-left md:text-center">#</h1>
              <div
                className="pointer-events-auto flex cursor-pointer flex-row items-center justify-start"
                onClick={() => setSortMethod("name")}
              >
                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
                  Name
                </h1>
                <SortSVG sortType="name" />
              </div>
              <div
                className="pointer-events-auto flex cursor-pointer flex-row items-center justify-end"
                onClick={() => setSortMethod("netWorth")}
              >
                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
                  Assets
                </h1>
                <SortSVG sortType="netWorth" />
              </div>
              <div
                className="pointer-events-auto hidden cursor-pointer flex-row items-center justify-end md:flex"
                onClick={() => setSortMethod("points")}
              >
                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
                  Points
                </h1>
                <SortSVG sortType="points" />
              </div>
              <div
                className="pointer-events-auto hidden cursor-pointer flex-row items-center justify-end md:flex"
                onClick={() => setSortMethod("shares")}
              >
                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
                  Shares
                </h1>
                <SortSVG sortType="shares" />
              </div>
              <div
                className="pointer-events-auto flex cursor-pointer flex-row items-center justify-end"
                onClick={() => setSortMethod("dailyChangePercent")}
              >
                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
                  Daily
                </h1>
                <SortSVG sortType="dailyChangePercent" />
              </div>
            </div>
            {
              // if data is not loaded, loading div
              !dataLoaded ? (
                <m.div
                  className="mt-5 flex h-[100vh] w-full flex-col items-center justify-start"
                  variants={rankingDataContainerVariants}
                >
                  <Loading />
                  <h1 className="my-5">This is fake delay :)</h1>
                </m.div>
              ) : (
                <m.div
                  initial="initial"
                  animate="animate"
                  exit="exit"
                  variants={rankingDataContainerVariants}
                >
                  {
                    // generate table rows
                    fakeData.map((entry: UserJSONEntry, index: number) => {
                      // if daily change is negative, make it red
                      let changeClass = " text-lime-500";
                      if (entry.daily_change_percent < 0) {
                        changeClass = " text-red-500";
                      }
                      return (
                        <m.div
                          className="inline-grid w-full grid-flow-col grid-cols-[1fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-700 px-5 py-2 text-right md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]"
                          key={entry.id}
                          variants={rankingDataLineVariants}
                        >
                          <h1 className="text-left md:text-center">
                            {index + 1}
                          </h1>
                          <Link
                            href={`/user/${entry.name}`}
                            className="overflow-hidden"
                          >
                            <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
                              {entry.name}
                            </h1>
                          </Link>
                          <h1>{entry.net_worth.toLocaleString("en-US")}</h1>
                          <h1 className="hidden md:block">
                            {entry.points.toLocaleString("en-US")}
                          </h1>
                          <h1 className="hidden md:block">
                            {entry.shares.toLocaleString("en-US")}
                          </h1>
                          <h1 className={changeClass}>
                            {(
                              Math.round(entry.daily_change_percent * 1000) / 10
                            ).toFixed(1) + "%"}
                          </h1>
                        </m.div>
                      );
                    })
                  }
                </m.div>
              )
            }
          </m.div>
        </div>
      </div>
    </>
  );
}

// header animation if needed
const headerVariants: Variants = {
  initial: {
    opacity: 0,
    y: -100,
  },
  animate: {
    opacity: 1,
    y: 0,
    transition: {
      delay: 1.0,
      duration: 1.0,
      type: "spring",
      bounce: 0.5,
      stiffness: 60,
    },
  },
};

// table container animation
const rankingCardVariants: Variants = {
  initial: {
    opacity: 0,
    y: 300,
  },
  animate: {
    opacity: 1,
    y: 0,
    transition: {
      duration: 3,
      delayChildren: 0.5,
      type: "spring",
      bounce: 0.5,
      stiffness: 40,
    },
  },
  exit: {
    opacity: 0,
    y: 175,
    transition: {
      duration: 0.5,
    },
  },
};

const rankingDataContainerVariants: Variants = {
  initial: {
    opacity: 0,
  },
  animate: {
    opacity: 1,
    transition: {
      duration: 1.0,
      staggerChildren: 0.045,
    },
  },
  exit: {
    opacity: 0,
    y: 150,
    transition: {
      duration: 0.5,
    },
  },
};

const rankingDataLineVariants: Variants = {
  initial: {
    opacity: 0,
  },
  animate: {
    opacity: 1,
    transition: {
      duration: 1.0,
    },
  },
};

Ranking.getLayout = function getLayout(page: ReactElement) {
  const metaTags = {
    title: "Ranking - toffee",
    description: "Top investors on toffee",
  };
  return <DashLayout metaTags={metaTags}>{page}</DashLayout>;
};

export default Ranking;