import React, { useEffect, useState } from "react";
import { NextPage } from "next";
import { useRouter } from "next/router";
import { toast } from "react-toastify";
import AdminCreateCommon from "@views/admin/AdminCreateCommon";
import Tag from "@models/Tag";
import TagApi from "@api/tagApi";
import { SignupForm } from "@models/Signup";
import SignupApi from "@api/signupApi";
import Event from "@models/Event";
import EventApi from "@api/eventApi";
import DatetimeWidget from "@components/Widgets/DatetimeWidget";
import SectionDividerWidget from "@components/Widgets/SectionDividerWidget";
import MarkdownEditorWidget from "@components/Widgets/MarkdownEditorWidget";

const widgets = {
  datetime: DatetimeWidget,
  section_divider: SectionDividerWidget,
  markdownEditor: MarkdownEditorWidget,
};

const buildSchema = (formData: Event, signupForms: SignupForm[], tags: Tag[]) => {
  const date = new Date(); const
    tomorrowDate = new Date();
  const currentDatetime = date.toISOString();
  tomorrowDate.setDate(tomorrowDate.getDate() + 1);
  const tomorrowDatetime = tomorrowDate.toISOString();

  const schema = {
    title: formData?.title_fi ?? "New Event",
    type: "object",
    required: ["title_fi", "title_en", "tags", "location_fi", "location_en", "start_time", "end_time", "description_fi", "description_en", "content_fi", "content_en"],
    properties: {
      tags: {
        type: "array",
        title: "Event tags",
        items: {
          type: "number",
          enum: tags.map((t) => t.id),
          enumNames: tags.map((t) => t.name_fi),
        },
        uniqueItems: true,
        default: [],
      },
      visible: {
        type: "boolean",
        title: "Visible",
        default: true,
      },
      start_time: {
        type: "string",
        title: "Start time",
        default: currentDatetime,
      },
      end_time: {
        type: "string",
        title: "End time",
        default: tomorrowDatetime,
      },
      signupForm: {
        type: "array",
        title: "Signup forms",
        items: {
          type: "number",
          // TODO: A bug here, DB must have at least one SignupForm, otherwise cannot submit
          enum: signupForms.map((form) => form.id),
          enumNames: signupForms.map((form) => form.title_fi),
        },
        uniqueItems: true,
        default: [],
      },
      image: {
        type: ["string", "null"],
        format: formData?.image ? "uri-reference" : "data-url",
        title: "Override tag icon with image",
        default: undefined,
      },
      finnish_section_divider: {
        title: "Finnish",
        type: "string",
      },
      title_fi: {
        type: "string",
        title: "Title",
        default: "",
      },
      description_fi: {
        type: "string",
        title: "Description",
        default: "",
      },
      content_fi: {
        type: "string",
        title: "Content",
        default: "",
      },
      location_fi: {
        type: "string",
        title: "Location",
        default: "",
      },
      english_section_divider: {
        title: "English",
        type: "string",
      },
      title_en: {
        type: "string",
        title: "Title",
        default: "",
      },
      description_en: {
        type: "string",
        title: "Description",
        default: "",
      },
      content_en: {
        type: "string",
        title: "Content",
        default: "",
      },
      location_en: {
        type: "string",
        title: "Location",
        default: "",
      },
    },
  };
  return schema;
};

const buildUISchema = () => {
  const uiSchema = {
    content_fi: {
      "ui:widget": "markdownEditor",
    },
    content_en: {
      "ui:widget": "markdownEditor",
    },
    start_time: {
      "ui:widget": "datetime",
    },
    end_time: {
      "ui:widget": "datetime",
    },
    image: {
      "ui:options": {
        accept: [".jpg", ".jpeg", ".png"],
      },
    },
    finnish_section_divider: {
      "ui:widget": "section_divider",
      "ui:options": {
        label: false,
      },
    },
    english_section_divider: {
      "ui:widget": "section_divider",
      "ui:options": {
        label: false,
      },
    },
  };
  return uiSchema;
};

const EventCreatePage: NextPage = () => {
  const [formData, setFormData] = useState<Event>(null);
  const [tags, setTags] = useState<Tag[]>([]);
  const [signupForms, setSignupForms] = useState<SignupForm[]>([]);
  const [error, setError] = useState<string>(null);

  const router = useRouter();

  let id: string;

  if (router.query?.id && router.query.id !== "create") {
    id = router.query.id as string;
  }

  useEffect(() => {
    TagApi.getTags()
      .then((res) => setTags(res))
      .catch((err) => setError(err));

    SignupApi.getForms(true)
      .then((res) => setSignupForms(res))
      .catch((err) => setError(err));

    const eventId = id && Number(id);
    if (eventId !== undefined) {
      EventApi.getEvent(eventId, true)
        .then((res) => setFormData({
          ...res,
          tags: (res.tags).map((inst) => inst.id) as any,
          signupForm: (res.signupForm).map((inst) => inst.id) as any,
        }))
        .catch((err) => setError(err));
    }
  }, [id]);

  const onSubmit = async (data: any) => {
    try {
      const payload = data.formData;
      payload.signup_id = payload.signupForm;
      payload.tag_id = payload.tags;
      if (typeof payload.image === "string" && payload.image.startsWith("http")) payload.image = undefined;

      if (payload.id === undefined) {
        const resp = await EventApi.createEvent(payload);
        // TODO: Backend return old data because of Prefetch (used for filtering invisble signupForms from GET)
        // Copy from old state instead...
        // resp.tags = (resp.tags as any).map(inst => inst.id);
        // resp.signupForm = (resp.signupForm as any).map(inst => inst.id);
        resp.tags = data.formData.tags;
        resp.signupForm = data.formData.signupForm;
        toast.success("Event created successfully 😎");
        router.push("/admin/events");
        setFormData(resp);
      } else {
        const resp = await EventApi.updateEvent(payload);
        // TODO: Backend return old data because of Prefetch (used for filtering invisble signupForms from GET)
        // Copy from old state instead...
        // resp.tags = (resp.tags as any).map(inst => inst.id);
        // resp.signupForm = (resp.signupForm as any).map(inst => inst.id);
        resp.tags = data.formData.tags;
        resp.signupForm = data.formData.signupForm;
        toast.success("Event updated successfully 😎");
        router.push("/admin/events");
        setFormData(resp);
      }
    } catch (err) {
      toast.error("Uh oh! Something went wrong! Try again later. 😟");
      setError(err);
    }
  };

  const onChange = (data: any) => setFormData(data.formData);
  const title = formData?.id
    ? `Edit Event "${formData.title_fi}"`
    : "Create Event";

  return (
    <AdminCreateCommon
      title={title}
      formData={formData}
      schema={buildSchema(formData, signupForms, tags)}
      UISchema={buildUISchema()}
      onChange={onChange}
      onSubmit={onSubmit}
      error={error}
      widgets={widgets}
    />
  );
};

export default EventCreatePage;
