import { useEffect, useRef } from "react";
import { Form, Link, redirect, useNavigation } from "react-router";
import type { Route } from "./+types/home";
import { createPost, deletePost, listPosts, listCredentials } from "~/lib/db.server";
import { renderMarkdown } from "~/lib/md.server";
import { getSession, commitSession } from "~/lib/session.server";

export async function loader({ request }: Route.LoaderArgs) {
  const session = await getSession(request.headers.get("Cookie"));
  const isAuthenticated = session.get("authenticated") === true;
  const hasCredentials = listCredentials().length > 0;
  const posts = listPosts();
  return {
    posts: posts.map((p) => ({ ...p, html: renderMarkdown(p.content) })),
    isAuthenticated,
    hasCredentials,
  };
}

export async function action({ request }: Route.ActionArgs) {
  const session = await getSession(request.headers.get("Cookie"));
  if (session.get("authenticated") !== true) {
    throw new Response("Unauthorized", { status: 401 });
  }

  const form = await request.formData();
  const intent = String(form.get("intent") ?? "create");

  if (intent === "delete") {
    const id = String(form.get("id") ?? "");
    if (id) deletePost(id);
    return redirect("/", {
      headers: { "Set-Cookie": await commitSession(session) },
    });
  }

  const content = String(form.get("content") ?? "").trim();
  if (!content) return { error: "内容を入力してください", content };
  if (content.length > 10000) return { error: "投稿が長すぎます（最大10,000文字）", content };

  createPost({ id: crypto.randomUUID(), content });
  return redirect("/", {
    headers: { "Set-Cookie": await commitSession(session) },
  });
}

export default function Home({ loaderData, actionData }: Route.ComponentProps) {
  const { posts, isAuthenticated, hasCredentials } = loaderData;
  const navigation = useNavigation();
  const isSubmitting = navigation.state === "submitting";
  const formRef = useRef<HTMLFormElement>(null);
  const wasSubmitting = useRef(false);

  useEffect(() => {
    if (navigation.state === "submitting") wasSubmitting.current = true;
    if (wasSubmitting.current && navigation.state === "idle" && !actionData?.error) {
      formRef.current?.reset();
      wasSubmitting.current = false;
    }
  }, [navigation.state, actionData?.error]);

  return (
    <div className="wrap">
      <header className="site-header">
        <h1>log</h1>
        <nav className="header-nav">
          {isAuthenticated ? (
            <Form method="post" action="/auth/logout">
              <button type="submit" className="logout-btn">ログアウト</button>
            </Form>
          ) : hasCredentials ? (
            <Link to="/auth/login" className="auth-link">ログイン</Link>
          ) : (
            <Link to="/auth/register" className="auth-link">登録</Link>
          )}
        </nav>
      </header>

      {isAuthenticated && (
        <div className="compose">
          <Form method="post" ref={formRef}>
            <input type="hidden" name="intent" value="create" />
            <textarea
              name="content"
              placeholder="Markdown で投稿..."
              rows={4}
              defaultValue={actionData?.content ?? ""}
              autoFocus
            />
            {actionData?.error && (
              <p className="error-msg">{actionData.error}</p>
            )}
            <div className="compose-row">
              <span className="hint">markdown</span>
              <button type="submit" disabled={isSubmitting}>
                {isSubmitting ? "投稿中…" : "投稿"}
              </button>
            </div>
          </Form>
        </div>
      )}

      <div className="feed">
        {posts.length === 0 && (
          <p className="empty">まだ投稿がありません</p>
        )}
        {posts.map((post) => (
          <article key={post.id} className="post">
            <div className="post-header">
              <time className="post-meta" dateTime={post.created_at + "Z"}>
                {formatDate(post.created_at)}
              </time>
              {isAuthenticated && (
                <Form method="post">
                  <input type="hidden" name="intent" value="delete" />
                  <input type="hidden" name="id" value={post.id} />
                  <button
                    type="submit"
                    className="delete-btn"
                    onClick={(e) => {
                      if (!confirm("この投稿を削除しますか？")) e.preventDefault();
                    }}
                  >
                    削除
                  </button>
                </Form>
              )}
            </div>
            <div
              className="prose"
              dangerouslySetInnerHTML={{ __html: post.html }}
            />
          </article>
        ))}
      </div>
    </div>
  );
}

function formatDate(isoUtc: string): string {
  return new Date(isoUtc + "Z").toLocaleString("ja-JP", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    timeZone: "Asia/Tokyo",
  });
}
