import React, { useState } from "react";
import Head from "next/head";
import { useRouter } from "next/router";
import { useSnapshot } from "valtio";
import { useTranslation } from "next-i18next";

import Linkify from "react-linkify";
import classNames from "classnames";

import * as AlertDialog from "@radix-ui/react-alert-dialog";
import CrossIcon from "~public/icons/Cross.svg";

import Button from "~components/Button";
import CharLimitedFieldset from "~components/CharLimitedFieldset";
import RaidDropdown from "~components/RaidDropdown";
import TextFieldset from "~components/TextFieldset";

import { accountState } from "~utils/accountState";
import { appState } from "~utils/appState";

import "./index.scss";
import Link from "next/link";
import { formatTimeAgo } from "~utils/timeAgo";

const emptyRaid: Raid = {
  id: "",
  name: {
    en: "",
    ja: "",
  },
  slug: "",
  level: 0,
  group: 0,
  element: 0,
};

// Props
interface Props {
  editable: boolean;
  updateCallback: (name?: string, description?: string, raid?: Raid) => void;
  deleteCallback: (
    event: React.MouseEvent<HTMLButtonElement, MouseEvent>
  ) => void;
}

const PartyDetails = (props: Props) => {
  const { party, raids } = useSnapshot(appState);
  const { account } = useSnapshot(accountState);

  const { t } = useTranslation("common");
  const router = useRouter();
  const locale = router.locale || "en";

  const nameInput = React.createRef<HTMLInputElement>();
  const descriptionInput = React.createRef<HTMLTextAreaElement>();
  const raidSelect = React.createRef<HTMLSelectElement>();

  const readOnlyClasses = classNames({
    PartyDetails: true,
    ReadOnly: true,
    Visible: !party.detailsVisible,
  });

  const editableClasses = classNames({
    PartyDetails: true,
    Editable: true,
    Visible: party.detailsVisible,
  });

  const emptyClasses = classNames({
    EmptyDetails: true,
    Visible: !party.detailsVisible,
  });

  const userClass = classNames({
    user: true,
    empty: !party.user,
  });

  const linkClass = classNames({
    wind: party && party.element == 1,
    fire: party && party.element == 2,
    water: party && party.element == 3,
    earth: party && party.element == 4,
    dark: party && party.element == 5,
    light: party && party.element == 6,
  });

  const [errors, setErrors] = useState<{ [key: string]: string }>({
    name: "",
    description: "",
  });

  function handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
    event.preventDefault();

    const { name, value } = event.target;
    let newErrors = errors;

    setErrors(newErrors);
  }

  function handleTextAreaChange(event: React.ChangeEvent<HTMLTextAreaElement>) {
    event.preventDefault();

    const { name, value } = event.target;
    let newErrors = errors;

    setErrors(newErrors);
  }

  function toggleDetails() {
    appState.party.detailsVisible = !appState.party.detailsVisible;
  }

  function updateDetails(event: React.MouseEvent) {
    const nameValue = nameInput.current?.value;
    const descriptionValue = descriptionInput.current?.value;
    const raid = raids.find((raid) => raid.slug === raidSelect.current?.value);

    props.updateCallback(nameValue, descriptionValue, raid);
    toggleDetails();
  }

  const userImage = () => {
    if (party.user)
      return (
        <img
          alt={party.user.picture.picture}
          className={`profile ${party.user.picture.element}`}
          srcSet={`/profile/${party.user.picture.picture}.png,
                            /profile/${party.user.picture.picture}@2x.png 2x`}
          src={`/profile/${party.user.picture.picture}.png`}
        />
      );
    else return <div className="no-user" />;
  };

  const userBlock = () => {
    return (
      <div className={userClass}>
        {userImage()}
        {party.user ? party.user.username : t("no_user")}
      </div>
    );
  };

  const linkedUserBlock = (user: User) => {
    return (
      <div>
        <Link href={`/${user.username}`} passHref>
          <a className={linkClass}>{userBlock()}</a>
        </Link>
      </div>
    );
  };

  const linkedRaidBlock = (raid: Raid) => {
    return (
      <div>
        <Link href={`/teams?raid=${raid.slug}`} passHref>
          <a className={`Raid ${linkClass}`}>{raid.name[locale]}</a>
        </Link>
      </div>
    );
  };

  const deleteButton = () => {
    if (party.editable) {
      return (
        <AlertDialog.Root>
          <AlertDialog.Trigger className="Button destructive">
            <span className="icon">
              <CrossIcon />
            </span>
            <span className="text">{t("buttons.delete")}</span>
          </AlertDialog.Trigger>
          <AlertDialog.Portal>
            <AlertDialog.Overlay className="Overlay" />
            <AlertDialog.Content className="Dialog">
              <AlertDialog.Title className="DialogTitle">
                {t("modals.delete_team.title")}
              </AlertDialog.Title>
              <AlertDialog.Description className="DialogDescription">
                {t("modals.delete_team.description")}
              </AlertDialog.Description>
              <div className="actions">
                <AlertDialog.Cancel className="Button modal">
                  {t("modals.delete_team.buttons.cancel")}
                </AlertDialog.Cancel>
                <AlertDialog.Action
                  className="Button modal destructive"
                  onClick={(e) => props.deleteCallback(e)}
                >
                  {t("modals.delete_team.buttons.confirm")}
                </AlertDialog.Action>
              </div>
            </AlertDialog.Content>
          </AlertDialog.Portal>
        </AlertDialog.Root>
      );
    } else {
      return "";
    }
  };

  const editable = (
    <section className={editableClasses}>
      <CharLimitedFieldset
        fieldName="name"
        placeholder="Name your team"
        value={party.name}
        limit={50}
        onChange={handleInputChange}
        error={errors.name}
        ref={nameInput}
      />
      <RaidDropdown
        showAllRaidsOption={false}
        currentRaid={party.raid?.slug || ""}
        ref={raidSelect}
      />
      <TextFieldset
        fieldName="name"
        placeholder={
          "Write your notes here\n\n\nWatch out for the 50% trigger!\nMake sure to click Fediel’s 1 first\nGood luck with RNG!"
        }
        value={party.description}
        onChange={handleTextAreaChange}
        error={errors.description}
        ref={descriptionInput}
      />

      <div className="bottom">
        <div className="left">
          {router.pathname !== "/new" ? deleteButton() : ""}
        </div>
        <div className="right">
          <Button active={true} onClick={toggleDetails}>
            {t("buttons.cancel")}
          </Button>

          <Button active={true} icon="check" onClick={updateDetails}>
            {t("buttons.save_info")}
          </Button>
        </div>
      </div>
    </section>
  );

  const readOnly = (
    <section className={readOnlyClasses}>
      <div className="info">
        <div className="left">
          {party.name ? <h1>{party.name}</h1> : ""}
          <div className="attribution">
            {party.user ? linkedUserBlock(party.user) : userBlock()}
            {party.raid ? linkedRaidBlock(party.raid) : ""}
            {party.created_at != undefined ? (
              <time
                className="last-updated"
                dateTime={new Date(party.created_at).toString()}
              >
                {formatTimeAgo(new Date(party.created_at), locale)}
              </time>
            ) : (
              ""
            )}
          </div>
        </div>
        <div className="right">
          {party.editable ? (
            <Button active={true} icon="edit" onClick={toggleDetails}>
              {t("buttons.show_info")}
            </Button>
          ) : (
            <div />
          )}
        </div>
      </div>
      {party.description ? (
        <p>
          <Linkify>{party.description}</Linkify>
        </p>
      ) : (
        ""
      )}
    </section>
  );

  const emptyDetails = (
    <div className={emptyClasses}>
      {party.editable ? (
        <Button active={true} icon="edit" onClick={toggleDetails}>
          {t("buttons.show_info")}
        </Button>
      ) : (
        <div />
      )}
    </div>
  );

  const generateTitle = () => {
    let title = party.raid ? `[${party.raid?.name[locale]}] ` : "";

    const username =
      party.user != null ? `@${party.user?.username}` : t("header.anonymous");

    if (party.name != null)
      title += t("header.byline", {
        partyName: party.name,
        username: username,
      });
    else if (party.name == null && party.editable && router.route === "/new")
      title = t("header.new_team");
    else
      title += t("header.untitled_team", {
        username: username,
      });

    return title;
  };

  return (
    <div>
      <Head>
        <title>{generateTitle()}</title>

        <meta property="og:title" content={generateTitle()} />
        <meta
          property="og:description"
          content={party.description ? party.description : ""}
        />
        <meta property="og:url" content="https://app.granblue.team" />
        <meta property="og:type" content="website" />

        <meta name="twitter:card" content="summary_large_image" />
        <meta property="twitter:domain" content="app.granblue.team" />
        <meta name="twitter:title" content={generateTitle()} />
        <meta
          name="twitter:description"
          content={party.description ? party.description : ""}
        />
      </Head>
      {editable && (party.name || party.description || party.raid)
        ? readOnly
        : emptyDetails}
      {editable}
    </div>
  );
};

export default PartyDetails;
