import { redirect } from "@remix-run/node";
import {
  unstable_createFileUploadHandler,
  unstable_parseMultipartFormData,
  json,
} from "@remix-run/node";
import { useLoaderData, Form, useActionData, Link } from "@remix-run/react";
import { useState } from "react";
import Overlay from "~/components/Overlay";
import prisma from "~/utils/db.server";

export async function action({ request, params }) {
  const threadId = params.threadId;
  if (!parseInt(threadId)) throw new Error("Bad route parameter");

  const clonedData = request.clone();
  const formData = await clonedData.formData();
  const post = formData.get("post");
  const replying = formData.get("replying");

  const fileUploadHandler = unstable_createFileUploadHandler({
    directory: "./public/uploads/",
    maxPartSize: 500000,
    file: ({ filename }) => {
      if (formData.get("anonymize"))
        return `${require("crypto").randomBytes(16).toString("hex")}.${
          filename.split(".").slice(-1)[0]
        }`;

      return filename;
    },
    filter: (data) => {
      const fileTypes = ["jpeg", "jpg", "png", "gif"];
      // if sent file is not an image, don't handle it
      if (!fileTypes.includes(data.contentType.split("/")[1])) return false;

      return true;
    },
  });

  const errors = {};

  let imageName;
  let multiPartformdata;
  try {
    multiPartformdata = await unstable_parseMultipartFormData(
      request,
      fileUploadHandler
    );
    multiPartformdata.get("image") !== null
      ? (imageName = multiPartformdata.get("image").name)
      : (imageName = null);
  } catch (err) {
    errors.image = "Image size too big";
  }
  if (typeof post !== "string" || post.length > 50 || post.length < 3) {
    errors.post = "Post too long or short";
  }

  if (replying !== "") {
    let currentThreadreplyids = [];
    const currentThread = await prisma.thread.findUnique({
      where: {
        id: parseInt(threadId),
      },
      include: {
        posts: true,
      },
    });
    currentThread.posts.map((post) => currentThreadreplyids.push(post.id));

    if (
      typeof replying !== "string" ||
      !parseInt(replying) ||
      !currentThreadreplyids.includes(parseInt(replying))
    ) {
      errors.replying = "bad reply id";
    }
  }

  if (Object.keys(errors).length) {
    return json(errors, { status: 422 });
  }

  const createPost = await prisma.post.create({
    data: {
      comment: post,
      imageName: imageName,
      replyingTo: replying ? parseInt(replying) : null,
      postId: parseInt(threadId),
    },
  });

  return redirect(`/threads/${threadId}`);
}

export async function loader({ params }) {
  const threadId = params.threadId;
  if (!parseInt(threadId)) throw new Error("Bad route parameter");

  const thread = await prisma.thread.findUnique({
    where: {
      id: parseInt(threadId),
    },
    include: {
      posts: {
        include: {
          replies: true,
        },
      },
    },
  });

  if (!thread) {
    throw new Error("Thread not found");
  }

  return thread;
}

export default function Thread() {
  const data = useLoaderData();
  const actionData = useActionData();
  const [replying, setReplying] = useState();

  return (
    <Overlay>
      <div className="flex flex-col">
        <div
          id="OP"
          className="bg-ctp-crust w-fit flex flex-col shadow-lg border-4 rounded p-4"
        >
          <span>
            <strong>{data.title}</strong> Post id: <strong>{data.id}</strong>{" "}
            Created at:{" "}
            <strong>{new Date(data.createdAt).toLocaleString()}</strong> Reply
            count: <strong>{data.posts.length}</strong>
          </span>
          <br />
          <div className="flex flex-col">
            <img
              className="w-60 max-h-96"
              src={`/uploads/${data.imageName}`}
              alt="post image"
            />
            <Link
              className=" text-xs text-ctp-surface0"
              to={`/uploads/${data.imageName}`}
              target="_blank"
              referrerPolicy="no-referrer"
            >
              Click to show full image
            </Link>
          </div>
          <p className="">{data.post}</p>
        </div>
        <ul className="m-8 ">
          {data.posts.map((post) => (
            <li
              id={`${post.id}`}
              className="rounded w-fit shadow p-4 m-4 odd:bg-ctp-mantle border even:bg-ctp-crust"
              key={post.id}
            >
              <div className="flex flex-wrap">
                <span>
                  Reply id: <strong>{post.id}</strong> Replied at:{" "}
                  <strong>{new Date(post.createdAt).toLocaleString()} </strong>
                </span>
                <Link
                  className="mx-2 text-ctp-rosewater hover:text-ctp-maroon hover:underline"
                  onClick={(event) => {
                    event.preventDefault();
                    document.getElementById(`bottom`).scrollIntoView(true);
                    setReplying(post.id);
                  }}
                  to={`#bottom`}
                >
                  Reply
                </Link>
                <ul className="flex flex-wrap space-x-1">
                  {post?.replies?.map((reply) => (
                    <li key={reply.id}>
                      <Link
                        onClick={(event) => {
                          event.preventDefault();
                          document
                            .getElementById(`${reply.id}`)
                            .scrollIntoView(true);
                        }}
                        className="text-ctp-teal hover:text-ctp-sky hover:underline"
                        to={`#${reply.id}`}
                      >
                        #{reply.id}
                      </Link>
                    </li>
                  ))}
                </ul>
              </div>
              {post.replyingTo ? (
                <Link
                  onClick={(event) => {
                    event.preventDefault();
                    document
                      .getElementById(`${post.replyingTo}`)
                      .scrollIntoView(true);
                  }}
                  className="font-semibold text-sm hover:underline"
                  to={`#${post.replyingTo}`}
                >
                  Replying to id: {post.replyingTo}
                </Link>
              ) : (
                ""
              )}
              {post.imageName !== null ? (
                <div className="flex flex-col">
                  <img
                    className="w-60 max-h-96"
                    src={`/uploads/${post.imageName}`}
                    alt="post image"
                  />
                  <Link
                    className=" text-xs text-ctp-surface0"
                    to={`/uploads/${post.imageName}`}
                    target="_blank"
                    referrerPolicy="no-referrer"
                  >
                    Click to show full image
                  </Link>
                </div>
              ) : (
                ""
              )}
              <p>{post.comment}</p>
            </li>
          ))}
        </ul>
      </div>
      <Form
        id="bottom"
        className="space-y-4 flex flex-col items-center"
        method="post"
        encType="multipart/form-data"
      >
        <label className="flex flex-col" htmlFor="text-input">
          {replying ? (
            <p className="text-center font-semibold text-ctp-black">
              Replying to reply id: {replying}{" "}
              <button
                className="text-ctp-sky hover:text-ctp-teal hover:underline"
                onClick={() => setReplying("")}
              >
                Reset
              </button>
            </p>
          ) : (
            ""
          )}
          <span className="font-semibold text-center text-ctp-subtext0">
            Post
          </span>{" "}
          <textarea
            className=" bg-ctp-surface0 m-1 p-1 rounded shadow shadow-ctp-overlay0"
            required
            minLength={3}
            name="post"
            type="text"
          />
          {actionData ? <p>{actionData.post}</p> : ""}
        </label>
        <label className="flex flex-col" htmlFor="image-upload">
          <span className="font-semibold text-center text-ctp-subtext0">
            Image (500kbps max)
          </span>
          <input
            className="block w-full px-3 py-1.5 text-base font-semibold text-ctp-text bg-ctp-surface0 bg-clip-padding rounded transition ease-in-out m-0"
            accept="image/*"
            type="file"
            id="image-upload"
            name="image"
          />
          <label htmlFor="anon">
            <span>Anonymize filename </span>
            <input type="checkbox" name="anonymize" id="anon-check" />
          </label>
          <p>{actionData?.image}</p>
        </label>
        <details class="flex items-center justify-center duration-300">
          <summary className="text-center text-ctp-subtext0 font-semibold cursor-pointer">
            Manual replying (needed when JS is disabled)
          </summary>
          <div class="flex flex-col items-center justify-center">
            <input
              className="bg-ctp-surface0 m-1 p-1 rounded shadow shadow-ctp-overlay0"
              placeholder="Enter a Reply ID"
              type="number"
              name="replying"
              value={replying}
            />
          </div>
        </details>
        <p className="text-ctp-red">{actionData?.replying}</p>

        <button
          className="bg-ctp-crust px-4 py-2 shadow rounded-full"
          type="submit"
        >
          Submit
        </button>
      </Form>
    </Overlay>
  );
}
