import formatDistanceToNow from "date-fns/formatDistanceToNow";
import { CopyToClipboard } from "react-copy-to-clipboard";
import React, { FC, useState, useEffect } from "react";
import { Flex } from "reflexbox/styled-components";
import styled, { css } from "styled-components";
import QRCode from "qrcode.react";
import Link from "next/link";

import { useStoreActions, useStoreState } from "../store";
import { removeProtocol, withComma } from "../utils";
import { useFormState } from "react-use-form-state";
import { NavButton, Button } from "./Button";
import { Col, RowCenter } from "./Layout";
import { ifProp } from "styled-tools";
import TextInput from "./TextInput";
import Table from "./CustomTable";
import Tooltip from "./Tooltip";
import ALink from "./ALink";
import Modal from "./Modal";
import Text from "./Text";
import Icon from "./Icon";
import Animation from "./Animation";

const Tr = styled(Flex).attrs({ as: "tr", px: [12, 12, 2] })``;
const Th = styled(Flex)``;
Th.defaultProps = { as: "th", flexBasis: 0, py: [12, 12, 3], px: [12, 12, 3] };

const Td = styled(Flex)<{ withFade?: boolean }>`
  position: relative;
  white-space: nowrap;

  ${ifProp(
    "withFade",
    css`
      :after {
        content: "";
        position: absolute;
        right: 0;
        top: 0;
        height: 100%;
        width: 16px;
        background: linear-gradient(to left, white, white, transparent);
      }

      tr:hover &:after {
        background: linear-gradient(
          to left,
          hsl(200, 14%, 98%),
          hsl(200, 14%, 98%),
          transparent
        );
      }
    `
  )}
`;
Td.defaultProps = {
  as: "td",
  fontSize: [15, 16],
  alignItems: "center",
  flexBasis: 0,
  py: [12, 12, 3],
  px: [12, 12, 3]
};

const Action = (props: React.ComponentProps<typeof Icon>) => (
  <Icon
    as="button"
    py={0}
    px={0}
    mr={2}
    size={[23, 24]}
    p={["4px", "5px"]}
    stroke="#666"
    {...props}
  />
);

const ogLinkFlex = { flexGrow: [1, 3, 7], flexShrink: [1, 3, 7] };
const createdFlex = { flexGrow: [1, 1, 3], flexShrink: [1, 1, 3] };
const shortLinkFlex = { flexGrow: [1, 1, 3], flexShrink: [1, 1, 3] };
const viewsFlex = {
  flexGrow: [0.5, 0.5, 1],
  flexShrink: [0.5, 0.5, 1],
  justifyContent: "flex-end"
};
const actionsFlex = { flexGrow: [1, 1, 2.5], flexShrink: [1, 1, 2.5] };

interface Form {
  count?: string;
  page?: string;
  search?: string;
}

const LinksTable: FC = () => {
  const links = useStoreState(s => s.links);
  const { get, deleteOne } = useStoreActions(s => s.links);
  const [copied, setCopied] = useState([]);
  const [qrModal, setQRModal] = useState(-1);
  const [deleteModal, setDeleteModal] = useState(-1);
  const [deleteLoading, setDeleteLoading] = useState(false);
  const [formState, { text }] = useFormState<Form>({ page: "1", count: "10" });

  const options = formState.values;
  const linkToDelete = links.items[deleteModal];

  useEffect(() => {
    get(options);
  }, [options.count, options.page]);

  const onSubmit = e => {
    e.preventDefault();
    get(options);
  };

  const onCopy = (index: number) => () => {
    setCopied([index]);
    setTimeout(() => {
      setCopied(s => s.filter(i => i !== index));
    }, 1500);
  };

  const onDelete = async () => {
    setDeleteLoading(true);
    await deleteOne({ id: linkToDelete.address, domain: linkToDelete.domain });
    await get(options);
    setDeleteLoading(false);
    setDeleteModal(-1);
  };

  const onNavChange = (nextPage: number) => () => {
    formState.setField("page", (parseInt(options.page) + nextPage).toString());
  };

  const Nav = (
    <Th
      alignItems="center"
      justifyContent="flex-end"
      flexGrow={1}
      flexShrink={1}
    >
      <Flex as="ul" m={0} p={0} style={{ listStyle: "none" }}>
        {["10", "25", "50"].map(c => (
          <Flex key={c} ml={[10, 12]}>
            <NavButton
              disabled={options.count === c}
              onClick={() => formState.setField("count", c)}
            >
              {c}
            </NavButton>
          </Flex>
        ))}
      </Flex>
      <Flex
        width="1px"
        height={20}
        mx={[3, 24]}
        style={{ backgroundColor: "#ccc" }}
      />
      <Flex>
        <NavButton
          onClick={onNavChange(-1)}
          disabled={options.page === "1"}
          px={2}
        >
          <Icon name="chevronLeft" size={15} />
        </NavButton>
        <NavButton
          onClick={onNavChange(1)}
          disabled={
            parseInt(options.page) * parseInt(options.count) > links.total
          }
          ml={12}
          px={2}
        >
          <Icon name="chevronRight" size={15} />
        </NavButton>
      </Flex>
    </Th>
  );

  return (
    <Col width={1200} maxWidth="95%" margin="40px 0 120px" my={6}>
      <Text as="h2" fontWeight={300} mb={3}>
        Recent shortened links.
      </Text>
      <Table scrollWidth="700px">
        <thead>
          <Tr justifyContent="space-between">
            <Th flexGrow={1} flexShrink={1}>
              <form onSubmit={onSubmit}>
                <TextInput
                  {...text("search")}
                  placeholder="Search..."
                  height={[30, 32]}
                  placeholderSize={[13, 13, 13, 13]}
                  fontSize={[14]}
                  pl={12}
                  pr={12}
                  width={[1]}
                  br="3px"
                  bbw="2px"
                />
              </form>
            </Th>
            {Nav}
          </Tr>
          <Tr>
            <Th {...ogLinkFlex}>Original URL</Th>
            <Th {...createdFlex}>Created</Th>
            <Th {...shortLinkFlex}>Short URL</Th>
            <Th {...viewsFlex}>Views</Th>
            <Th {...actionsFlex}></Th>
          </Tr>
        </thead>
        <tbody style={{ opacity: links.loading ? 0.4 : 1 }}>
          {!links.items.length ? (
            <Tr width={1} justifyContent="center">
              <Td flex="1 1 auto" justifyContent="center">
                <Text as="p" fontWeight={300} fontSize={18}>
                  {links.loading ? "Loading links..." : "No links to show."}
                </Text>
              </Td>
            </Tr>
          ) : (
            <>
              {links.items.map((l, index) => (
                <Tr>
                  <Td {...ogLinkFlex} withFade>
                    <ALink href={l.target}>{l.target}</ALink>
                  </Td>
                  <Td {...createdFlex}>{`${formatDistanceToNow(
                    new Date(l.created_at)
                  )} ago`}</Td>
                  <Td {...shortLinkFlex} withFade>
                    {copied.includes(index) ? (
                      <Animation
                        offset="10px"
                        duration="0.2s"
                        alignItems="center"
                      >
                        <Icon
                          size={[15, 24]}
                          py={0}
                          px={0}
                          mr={2}
                          p="3px"
                          name="check"
                          strokeWidth="3"
                          stroke="hsl(144, 50%, 60%)"
                        />
                      </Animation>
                    ) : (
                      <Animation offset="-10px" duration="0.2s">
                        <CopyToClipboard
                          text={l.shortLink}
                          onCopy={onCopy(index)}
                        >
                          <Action
                            name="copy"
                            strokeWidth="2.5"
                            stroke="hsl(144, 40%, 57%)"
                            backgroundColor="hsl(144, 100%, 96%)"
                          />
                        </CopyToClipboard>
                      </Animation>
                    )}
                    <ALink href={l.shortLink}>
                      {removeProtocol(l.shortLink)}
                    </ALink>
                  </Td>
                  <Td {...viewsFlex}>{withComma(l.visit_count)}</Td>
                  <Td {...actionsFlex} justifyContent="flex-end">
                    {l.password && (
                      <>
                        <Tooltip id={`${index}-tooltip-password`}>
                          Password protected
                        </Tooltip>
                        <Action
                          as="span"
                          data-tip
                          data-for={`${index}-tooltip-password`}
                          name="key"
                          stroke="#bbb"
                          strokeWidth="2.5"
                          backgroundColor="none"
                        />
                      </>
                    )}
                    {l.visit_count > 0 && (
                      <Link
                        href={`/stats?id=${l.id}${
                          l.domain ? `&domain=${l.domain}` : ""
                        }`}
                      >
                        <Action
                          name="pieChart"
                          stroke="hsl(260, 100%, 69%)"
                          strokeWidth="2.5"
                          backgroundColor="hsl(260, 100%, 96%)"
                        />
                      </Link>
                    )}
                    <Action
                      name="qrcode"
                      stroke="none"
                      fill="hsl(0, 0%, 35%)"
                      backgroundColor="hsl(0, 0%, 94%)"
                      onClick={() => setQRModal(index)}
                    />
                    <Action
                      mr={0}
                      name="trash"
                      stroke="hsl(0, 100%, 69%)"
                      strokeWidth="2"
                      backgroundColor="hsl(0, 100%, 96%)"
                      onClick={() => setDeleteModal(index)}
                    />
                  </Td>
                </Tr>
              ))}
            </>
          )}
        </tbody>
        <tfoot>
          <Tr justifyContent="flex-end">{Nav}</Tr>
        </tfoot>
      </Table>
      <Modal
        id="table-qrcode-modal"
        minWidth="max-content"
        show={qrModal > -1}
        closeHandler={() => setQRModal(-1)}
      >
        {links.items[qrModal] && (
          <RowCenter width={192}>
            <QRCode size={192} value={links.items[qrModal].shortLink} />
          </RowCenter>
        )}
      </Modal>
      <Modal
        id="delete-custom-domain"
        show={deleteModal > -1}
        closeHandler={() => setDeleteModal(-1)}
      >
        {linkToDelete && (
          <>
            <Text as="h2" fontWeight={700} mb={24} textAlign="center">
              Delete link?
            </Text>
            <Text as="p" textAlign="center">
              Are you sure do you want to delete the link{" "}
              <Text as="span" fontWeight={700}>
                "{removeProtocol(linkToDelete.shortLink)}"
              </Text>
              ?
            </Text>
            <Flex justifyContent="center" mt={44}>
              {deleteLoading ? (
                <>
                  <Icon name="spinner" size={20} stroke="#888" />
                </>
              ) : (
                <>
                  <Button
                    color="gray"
                    mr={3}
                    onClick={() => setDeleteModal(-1)}
                  >
                    Cancel
                  </Button>
                  <Button color="blue" ml={3} onClick={onDelete}>
                    <Icon name="trash" stroke="white" mr={2} />
                    Delete
                  </Button>
                </>
              )}
            </Flex>
          </>
        )}
      </Modal>
    </Col>
  );
};

export default LinksTable;
