import * as React from "react";
import { Field, Formik } from "formik";
import styled from "styled-components";

import { Button, Icon } from "../atoms";
import { IMockResponse, IMockResponseRaw } from "../../interface/mock";
import { IMethod } from "../../interface/network";
import MultiSelect from "../../components/multiselect";
import { getError } from "../../services/helper";
import { getNetworkMethodList } from "../../services/constants";
import Response from "./Response";
import Description from "./Description";
import Tabs from "../../components/tabs";

const methods = getNetworkMethodList();

export const Label = styled("label")`
  margin-bottom: 4px;
  font-weight: 700;
`;

export const Input = styled(Field).attrs({ id: "mock-create-input" })<{
  small?: boolean;
  marginRight?: boolean;
}>`
  border: 1px solid ${({ theme }) => theme.colors.border};
  border-radius: 4px;
  border-style: solid;
  ${({ small }) => small && `width: 124px;`};
  ${({ marginRight }) => marginRight && `margin-right: 8px;`};
`;

export const FieldWrapper = styled("div")`
  display: flex;
  flex-direction: column;
  flex-grow: 2;
`;

export const Group = styled.div.attrs({ className: "mock-create-group" })<{
  grow?: boolean;
}>`
  display: flex;
  align-items: center;
  margin-bottom: 8px;
  ${({ grow }) => (grow ? "flex-grow: 2;" : "")}
  ${FieldWrapper}:not(:last-child) {
    margin-right: 16px;
  }
`;

const Actions = styled.div``;

const StyledForm = styled("form")`
  padding: 8px 16px;
  height: 100%;
  display: flex;
  flex-direction: column;
`;

const Error = styled("p")`
  color: ${({ theme }) => theme.colors.alert} !important;
  height: 16px;
  margin-bottom: 8px;
`;

const StyledTabs = styled(Tabs)`
  margin-bottom: 2px;
`;

type IFormValues = Omit<IMockResponse, "id" | "createdOn">;

interface IProps {
  mock?: IMockResponseRaw;
  onSubmit: (values: IFormValues) => void;
  onCancel: () => void;
  jsonEditor?: {
    className?: string;
    style?: React.CSSProperties;
  };
}

const MockForm = ({ mock, onSubmit, onCancel, jsonEditor = {} }: IProps) => {
  const initialValues: IFormValues = {
    method: "GET",
    url: "",
    status: 200,
    delay: 500,
    response: "",
    active: true,
    headers: [],
    description: "",
    ...mock,
  };

  // RESPONSE | DESCRIPTION
  const [view, setView] = React.useState(0);

  return (
    <Formik
      initialValues={initialValues}
      onSubmit={(values) => onSubmit(values)}
      onReset={() => {}}
      validateOnBlur
      validate={(values) => {
        const errors: Record<string, string> = {};

        if (
          values.headers.length > 0 &&
          (!values.headers[values.headers.length - 1].name ||
            !values.headers[values.headers.length - 1].value)
        ) {
          errors.headers = "Each header pair should have name & value";
        }

        return errors;
      }}
    >
      {({
        setFieldValue,
        values,
        errors,
        handleReset,
        handleSubmit,
        isValid,
        setFieldError,
        setFieldTouched,
        handleChange,
        handleBlur,
      }) => {
        return (
          <StyledForm onReset={handleReset} onSubmit={handleSubmit}>
            <Group>
              <FieldWrapper style={{ flexGrow: 0 }}>
                <Label>Status:</Label>
                <MultiSelect
                  onSelect={(index) => {
                    setFieldValue("active", index ? false : true);
                  }}
                  options={["Active", "Inactive"]}
                  selected={values.active ? 0 : 1}
                />
              </FieldWrapper>
              <FieldWrapper style={{ flexGrow: 3 }}>
                <Label>URL:</Label>
                <Input required name="url"></Input>
              </FieldWrapper>
            </Group>
            <Group>
              <FieldWrapper className="mock-create-method">
                <Label>Method:</Label>
                <MultiSelect
                  onSelect={(index) => {
                    setFieldValue("method", methods[index]);
                  }}
                  options={methods}
                  selected={methods.indexOf(values.method as IMethod)}
                />
              </FieldWrapper>
              <FieldWrapper className="mock-create-status">
                <Label>Status:</Label>
                <Input small required name="status" type="number"></Input>
              </FieldWrapper>
              <FieldWrapper className="mock-create-delay">
                <Label>Delay (in ms):</Label>
                <Input small required name="delay" type="number"></Input>
              </FieldWrapper>
            </Group>
            <Group
              grow
              style={{
                overflow: "hidden",
                display: "flex",
                flexDirection: "column",
                alignItems: "unset",
              }}
            >
              <StyledTabs
                selected={view}
                tabs={["Response", "Description"]}
                onChange={(selected) => {
                  if (
                    selected === 1 &&
                    values.headers.length &&
                    !values.headers[values.headers.length - 1].name &&
                    !values.headers[values.headers.length - 1].value
                  ) {
                    setFieldValue("headers", []);
                  }
                  setView(selected);
                }}
              />
              {view === 0 && (
                <Response
                  mock={mock}
                  values={values}
                  errors={errors}
                  setFieldError={setFieldError}
                  setFieldValue={setFieldValue}
                  handleBlur={handleBlur}
                  handleChange={handleChange}
                />
              )}
              {view === 1 && (
                <Description
                  description={values.description}
                  handleChange={handleChange}
                  handleBlur={handleBlur}
                />
              )}
            </Group>
            <Group style={{ justifyContent: "space-between" }}>
              <Error>{getError(errors as any) || " "}</Error>
              <Actions>
                <Button
                  style={{ marginRight: 16 }}
                  disabled={!isValid}
                  type="submit"
                  background="primary"
                  color="white"
                >
                  Save
                </Button>
                <Button onClick={() => onCancel()} type="button">
                  Cancel
                </Button>
              </Actions>
            </Group>
          </StyledForm>
        );
      }}
    </Formik>
  );
};

export default MockForm;