import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import { PageErrorFragment } from "@saleor/fragments/types/PageErrorFragment";
import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment";
import { PageErrorCode, ProductErrorCode } from "@saleor/types/globalTypes";
import { getProductErrorMessage } from "@saleor/utils/errors";
import getPageErrorMessage from "@saleor/utils/errors/page";
import classNames from "classnames";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import slugify from "slugify";

import CardTitle from "../CardTitle";
import FormSpacer from "../FormSpacer";

enum SeoField {
  slug = "slug",
  title = "seoTitle",
  description = "seoDescription"
}

const DEFAULT_INPUT_MESSAGE =
  "If empty, the preview shows what will be autogenerated.";

interface Error {
  __typename: "ProductError" | "PageError";
  field: string | null;
  code: ProductErrorCode | PageErrorCode;
}

const SLUG_REGEX = /^[a-z0-9]+(?:[\-a-z0-9]+)*$/;

const useStyles = makeStyles(
  theme => ({
    addressBar: {
      color: "#006621",
      fontSize: "13px",
      lineHeight: "16px",
      marginBottom: "2px",
      overflow: "hidden",
      textOverflow: "ellipsis",
      whiteSpace: "nowrap"
    },
    container: {
      width: "100%"
    },
    descriptionBar: {
      color: "#545454",
      fontSize: "13px",
      lineHeight: "18px",
      overflowWrap: "break-word"
    },
    helperText: {
      marginBottom: theme.spacing(3)
    },
    label: {
      flex: 1
    },
    labelContainer: {
      "& span": {
        paddingRight: 30
      },
      display: "flex"
    },
    preview: {
      minHeight: theme.spacing(10)
    },
    title: {
      padding: 0
    },
    titleBar: {
      color: "#1a0dab",
      fontSize: "18px",
      lineHeight: "21px",
      overflowWrap: "break-word",
      textDecoration: "none",
      wordWrap: "break-word"
    }
  }),
  { name: "SeoForm" }
);

interface SeoFormProps {
  description?: string;
  descriptionPlaceholder: string;
  disabled?: boolean;
  errors?: ProductErrorFragment[] | PageErrorFragment[];
  loading?: boolean;
  helperText?: string;
  isCreating?: boolean;
  title: string;
  slug: string;
  slugPlaceholder?: string;
  titlePlaceholder: string;
  onChange(event: any);
  onClick?();
}

const SeoForm: React.FC<SeoFormProps> = props => {
  const {
    description,
    descriptionPlaceholder,
    disabled,
    errors,
    helperText,
    isCreating = false,
    loading,
    title,
    slug,
    slugPlaceholder,
    titlePlaceholder,
    onChange
  } = props;
  const classes = useStyles(props);

  const intl = useIntl();

  const [expanded, setExpansionStatus] = React.useState(false);

  const toggleExpansion = () => setExpansionStatus(!expanded);

  const shouldDisplayHelperText = helperText && !expanded;

  const getFilteredErrors = () =>
    (errors as Error[])?.filter(({ field }) =>
      Object.keys(SeoField).includes(field)
    ) || [];

  const getError = (fieldName: SeoField) =>
    getFilteredErrors().find(({ field }) => fieldName === field);

  const isError = (fieldName: SeoField) => !!getError(fieldName);

  const getSlugHelperText = () => {
    const error = isError(SeoField.slug);

    if (isCreating && !error) {
      return intl.formatMessage({
        defaultMessage: DEFAULT_INPUT_MESSAGE
      });
    }

    if (error) {
      return getSlugErrorHelperText();
    }

    return "";
  };

  const getSlugErrorHelperText = () => {
    const error = getError(SeoField.slug);
    const { __typename: type } = error;

    return type === "ProductError"
      ? getProductErrorMessage(error as ProductErrorFragment, intl)
      : getPageErrorMessage(error as PageErrorFragment, intl);
  };

  const handleSlugChange = event => {
    const { value } = event.target;

    if (value === "" || !!value.match(SLUG_REGEX)) {
      onChange(event);
    }
  };

  return (
    <Card>
      <CardTitle
        title={intl.formatMessage({
          defaultMessage: "Search Engine Preview"
        })}
        toolbar={
          <Button color="primary" variant="text" onClick={toggleExpansion}>
            <FormattedMessage
              defaultMessage="Edit website SEO"
              description="button"
            />
          </Button>
        }
      />
      <CardContent>
        {shouldDisplayHelperText && (
          <Typography
            className={classNames({ [classes.helperText]: expanded })}
          >
            {helperText}
          </Typography>
        )}
        {expanded && (
          <div className={classes.container}>
            <TextField
              error={isError(SeoField.slug)}
              name={SeoField.slug}
              label={
                <div className={classes.labelContainer}>
                  <div className={classes.label}>
                    <FormattedMessage defaultMessage="Slug" />
                  </div>
                  {slug?.length > 0 && (
                    <span>
                      <FormattedMessage
                        defaultMessage="{numberOfCharacters} of {maxCharacters} characters"
                        description="character limit"
                        values={{
                          maxCharacters: 70,
                          numberOfCharacters: slug?.length
                        }}
                      />
                    </span>
                  )}
                </div>
              }
              helperText={getSlugHelperText()}
              value={slug?.slice(0, 69)}
              disabled={loading || disabled}
              placeholder={slug || slugify(slugPlaceholder, { lower: true })}
              onChange={handleSlugChange}
              fullWidth
            />
            <FormSpacer />
            <TextField
              name={SeoField.title}
              error={isError(SeoField.title)}
              label={
                <div className={classes.labelContainer}>
                  <div className={classes.label}>
                    <FormattedMessage defaultMessage="Search engine title" />
                  </div>
                  {title?.length > 0 && (
                    <span>
                      <FormattedMessage
                        defaultMessage="{numberOfCharacters} of {maxCharacters} characters"
                        description="character limit"
                        values={{
                          maxCharacters: 70,
                          numberOfCharacters: title.length
                        }}
                      />
                    </span>
                  )}
                </div>
              }
              helperText={intl.formatMessage({
                defaultMessage: DEFAULT_INPUT_MESSAGE
              })}
              value={title?.slice(0, 69)}
              disabled={loading || disabled}
              placeholder={titlePlaceholder}
              onChange={onChange}
              fullWidth
            />
            <FormSpacer />
            <TextField
              error={isError(SeoField.description)}
              name={SeoField.description}
              label={
                <div className={classes.labelContainer}>
                  <div className={classes.label}>
                    <FormattedMessage defaultMessage="Search engine description" />
                  </div>
                  {description?.length > 0 && (
                    <span>
                      <FormattedMessage
                        defaultMessage="{numberOfCharacters} of {maxCharacters} characters"
                        description="character limit"
                        values={{
                          maxCharacters: 300,
                          numberOfCharacters: description.length
                        }}
                      />
                    </span>
                  )}
                </div>
              }
              helperText={intl.formatMessage({
                defaultMessage: DEFAULT_INPUT_MESSAGE
              })}
              value={description?.slice(0, 299)}
              onChange={onChange}
              disabled={loading || disabled}
              fullWidth
              multiline
              placeholder={descriptionPlaceholder}
              rows={10}
            />
          </div>
        )}
      </CardContent>
    </Card>
  );
};
SeoForm.displayName = "SeoForm";
export default SeoForm;
