"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import Image from "next/image";
import { QRCodeSVG } from "qrcode.react";
import { nip19 } from "nostr-tools";
import { Navbar } from "@/components/public/Navbar";
import { Footer } from "@/components/public/Footer";
import { Button } from "@/components/ui/Button";
import { api } from "@/lib/api";
import { useAuth } from "@/hooks/useAuth";
import { formatDate } from "@/lib/utils";
import { cn } from "@/lib/utils";
import { shortenPubkey } from "@/lib/nostr";
import { Copy, Check, Heart, Zap } from "lucide-react";

type BoardMessage = {
  id: string;
  paymentHash: string;
  content: string;
  authorName: string;
  pubkey: string | null;
  profilePic: string | null;
  satsPaid: number;
  likeCount: number;
  createdAt: string;
};

type PayPhase = "idle" | "polling" | "confirming" | "paid";

const MAX_LEN = 300;

function BoardAvatar({
  picture,
  name,
  size = 40,
}: {
  picture?: string | null;
  name: string;
  size?: number;
}) {
  const [err, setErr] = useState(false);
  const initial = name.slice(0, 1).toUpperCase() || "?";
  if (picture && !err) {
    return (
      <Image
        src={picture}
        alt=""
        width={size}
        height={size}
        className="rounded-full object-cover shrink-0"
        style={{ width: size, height: size }}
        onError={() => setErr(true)}
        unoptimized
      />
    );
  }
  return (
    <div
      className="rounded-full bg-surface-container-high flex items-center justify-center text-on-surface font-bold text-sm shrink-0"
      style={{ width: size, height: size }}
    >
      {initial}
    </div>
  );
}

export default function BoardPage() {
  const { user } = useAuth();
  const [config, setConfig] = useState<{
    priceSats: number;
    bbeZapPubkey: string | null;
    bbeZapAddress: string | null;
  } | null>(null);
  const [messages, setMessages] = useState<BoardMessage[]>([]);
  const [content, setContent] = useState("");
  const [guestName, setGuestName] = useState("");
  const [postAsAnon, setPostAsAnon] = useState(false);
  const [payPhase, setPayPhase] = useState<PayPhase>("idle");
  const [payError, setPayError] = useState("");
  const [invoice, setInvoice] = useState<{ pr: string; hash: string } | null>(null);
  const [copied, setCopied] = useState(false);
  const [localLikes, setLocalLikes] = useState<Record<string, number>>({});
  const [highlightPaymentHash, setHighlightPaymentHash] = useState<string | null>(null);
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const loadMessages = useCallback(async () => {
    const list = await api.getBoardMessages();
    setMessages(list as BoardMessage[]);
  }, []);

  const loadConfig = useCallback(async () => {
    const c = await api.getBoardConfig();
    setConfig(c);
  }, []);

  useEffect(() => {
    loadConfig().catch(() => {});
  }, [loadConfig]);

  useEffect(() => {
    loadMessages().catch(() => {});
    const t = setInterval(() => {
      loadMessages().catch(() => {});
    }, 12_000);
    return () => clearInterval(t);
  }, [loadMessages]);

  useEffect(() => {
    return () => {
      if (pollRef.current) clearInterval(pollRef.current);
    };
  }, []);

  const displayName = user?.name || user?.displayName || "";
  const npub = user?.pubkey ? nip19.npubEncode(user.pubkey) : "";
  const shortNpub = npub.length > 20 ? `${npub.slice(0, 14)}…${npub.slice(-12)}` : npub;

  const handlePayAndPost = async () => {
    setPayError("");
    const trimmed = content.trim();
    if (!trimmed) {
      setPayError("Write a message first.");
      return;
    }
    if (trimmed.length > MAX_LEN) {
      setPayError(`Message must be ${MAX_LEN} characters or fewer.`);
      return;
    }

    try {
      const body: Parameters<typeof api.createBoardInvoice>[0] = { content: trimmed };
      if (user?.pubkey && !postAsAnon) {
        body.pubkey = user.pubkey;
        body.name = displayName || undefined;
        body.profilePic = user.picture;
      } else {
        const n = guestName.trim();
        if (n) body.name = n;
      }
      body.postAsAnon = !!(user?.pubkey && postAsAnon);

      const inv = await api.createBoardInvoice(body);
      setHighlightPaymentHash(inv.payment_hash);
      setInvoice({ pr: inv.payment_request, hash: inv.payment_hash });
      setPayPhase("polling");

      if (pollRef.current) clearInterval(pollRef.current);
      pollRef.current = setInterval(async () => {
        try {
          const status = await api.getBoardPaymentStatus(inv.payment_hash);
          if (!status.paid) return;

          // Payment detected — try to ensure the message row exists
          setPayPhase("confirming");
          setInvoice(null);

          if (!status.messageCreated) {
            // Webhook may not have fired yet; call confirm to create the row
            await api.confirmBoardPayment(inv.payment_hash).catch(() => {});
          }

          // Poll until the message actually appears in the list (max ~30s)
          let found = false;
          for (let attempt = 0; attempt < 15; attempt++) {
            const list = await api.getBoardMessages();
            setMessages(list as BoardMessage[]);
            if (list.some((m) => m.paymentHash === inv.payment_hash)) {
              found = true;
              break;
            }
            // Try confirm again if first attempt didn't work
            if (attempt === 2) {
              await api.confirmBoardPayment(inv.payment_hash).catch(() => {});
            }
            await new Promise((r) => setTimeout(r, 2000));
          }

          if (pollRef.current) clearInterval(pollRef.current);
          pollRef.current = null;

          if (found) {
            setPayPhase("paid");
            setContent("");
            setGuestName("");
            setPostAsAnon(false);
            setTimeout(() => {
              setPayPhase("idle");
              setHighlightPaymentHash(null);
            }, 4000);
          } else {
            setPayPhase("idle");
            setPayError("Payment received but message is delayed — it will appear shortly.");
          }
        } catch {
          /* keep polling */
        }
      }, 2000);
    } catch (e: unknown) {
      setPayPhase("idle");
      setPayError(e instanceof Error ? e.message : "Could not create invoice.");
    }
  };

  const copyPr = async () => {
    if (!invoice?.pr) return;
    await navigator.clipboard.writeText(invoice.pr);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  const bumpLike = async (msg: BoardMessage) => {
    if (!user) return;
    try {
      const { likeCount } = await api.likeBoardMessage(msg.id);
      setLocalLikes((prev) => ({ ...prev, [msg.id]: likeCount }));
    } catch (e: unknown) {
      setPayError(e instanceof Error ? e.message : "Like failed");
    }
  };

  const handleZap = async (msg: BoardMessage) => {
    const zapAddress = config?.bbeZapAddress;
    const fallbackPub = config?.bbeZapPubkey;

    try {
      const w = window as unknown as {
        nostr?: { zap?: (args: Record<string, unknown>) => Promise<unknown> };
      };
      if (msg.pubkey && w.nostr?.zap) {
        await w.nostr.zap({
          pubkey: msg.pubkey,
          amount: 21,
          comment: "BBE board zap",
        });
        return;
      }
    } catch {
      /* fall through */
    }

    if (msg.pubkey) {
      window.open(`https://njump.me/${nip19.npubEncode(msg.pubkey)}`, "_blank", "noopener,noreferrer");
      return;
    }

    if (zapAddress) {
      const addr = zapAddress.replace(/^lightning:/i, "");
      window.location.href = `lightning:${addr}`;
      return;
    }

    if (fallbackPub) {
      try {
        window.open(
          `https://njump.me/${nip19.npubEncode(fallbackPub)}`,
          "_blank",
          "noopener,noreferrer"
        );
      } catch {
        setPayError("Invalid BOARD_ZAP_PUBKEY on server (expected hex pubkey).");
      }
      return;
    }

    setPayError("Zap: configure BOARD_ZAP_LN_ADDRESS or BOARD_ZAP_PUBKEY on the server.");
  };

  const len = content.length;

  return (
    <>
      <Navbar />
      <div className="min-h-screen pb-20">
        <div className="max-w-3xl mx-auto px-8 pt-16 pb-10">
          <h1 className="text-4xl font-black mb-2">Message board</h1>
          <p className="text-on-surface-variant text-lg mb-10">
            Pay {config?.priceSats ?? "…"} sats via Lightning to post. Messages are public and moderated.
          </p>

          <section className="rounded-2xl border border-outline-variant/30 bg-surface-container-low p-6 mb-12">
            <h2 className="text-lg font-bold text-on-surface mb-4">Post a message</h2>

            {user && !postAsAnon ? (
              <div className="flex items-center gap-3 mb-4 p-3 rounded-xl bg-surface-container">
                <BoardAvatar picture={user.picture} name={displayName || "You"} />
                <div className="min-w-0">
                  <p className="font-semibold text-on-surface truncate">{displayName || "Nostr user"}</p>
                  <p className="text-xs font-mono text-on-surface-variant truncate" title={npub}>
                    {shortNpub}
                  </p>
                </div>
              </div>
            ) : (
              <div className="space-y-3 mb-4">
                {user && (
                  <label className="flex items-center gap-2 text-sm text-on-surface-variant cursor-pointer">
                    <input
                      type="checkbox"
                      checked={postAsAnon}
                      onChange={(e) => setPostAsAnon(e.target.checked)}
                      className="rounded border-outline-variant"
                    />
                    Post as anon (hide Nostr profile)
                  </label>
                )}
                {!user || postAsAnon ? (
                  <div>
                    <label className="block text-sm font-medium text-on-surface-variant mb-1">
                      Name (optional)
                    </label>
                    <input
                      type="text"
                      value={guestName}
                      onChange={(e) => setGuestName(e.target.value)}
                      placeholder="Guest"
                      maxLength={80}
                      className="w-full rounded-lg border border-outline-variant bg-surface px-3 py-2 text-on-surface"
                    />
                  </div>
                ) : null}
              </div>
            )}

            <textarea
              value={content}
              onChange={(e) => setContent(e.target.value.slice(0, MAX_LEN))}
              placeholder="What’s on your mind?"
              rows={4}
              maxLength={MAX_LEN}
              className="w-full rounded-xl border border-outline-variant bg-surface px-4 py-3 text-on-surface placeholder:text-on-surface-variant/50 resize-y min-h-[120px]"
            />
            <div className="flex justify-between items-center mt-2 text-sm text-on-surface-variant">
              <span>
                {len}/{MAX_LEN}
              </span>
              {payPhase === "polling" && (
                <span className="text-primary font-medium animate-pulse">Awaiting payment…</span>
              )}
              {payPhase === "confirming" && (
                <span className="text-primary font-medium animate-pulse">Payment received — publishing…</span>
              )}
              {payPhase === "paid" && <span className="text-green-500 font-medium">Posted!</span>}
            </div>

            {payError && <p className="text-error text-sm mt-3">{payError}</p>}

            <div className="mt-4 flex flex-wrap gap-3">
              <Button
                variant="primary"
                size="md"
                onClick={handlePayAndPost}
                disabled={payPhase === "polling" || payPhase === "confirming" || !content.trim()}
              >
                Pay & post
              </Button>
            </div>

            {invoice && payPhase === "polling" && (
              <div className="mt-8 p-4 rounded-xl bg-surface-container border border-outline-variant/40">
                <p className="text-sm text-on-surface-variant mb-3">Scan or copy the Lightning invoice:</p>
                <div className="flex flex-col sm:flex-row gap-6 items-start">
                  <div className="bg-white p-3 rounded-lg shrink-0">
                    <QRCodeSVG value={invoice.pr} size={180} level="M" />
                  </div>
                  <div className="flex-1 min-w-0 space-y-2">
                    <button
                      type="button"
                      onClick={copyPr}
                      className="inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline"
                    >
                      {copied ? <Check size={16} /> : <Copy size={16} />}
                      {copied ? "Copied" : "Copy invoice"}
                    </button>
                    <p className="text-xs font-mono break-all text-on-surface-variant max-h-32 overflow-y-auto">
                      {invoice.pr}
                    </p>
                  </div>
                </div>
              </div>
            )}
          </section>

          <section>
            <h2 className="text-xl font-bold mb-4">Messages</h2>
            <ul className="space-y-4">
              {messages.map((m) => {
                const likes = localLikes[m.id] ?? m.likeCount;
                const isNew = highlightPaymentHash && m.paymentHash === highlightPaymentHash;
                return (
                  <li
                    key={m.id}
                    className={cn(
                      "rounded-2xl border p-5 transition-shadow duration-500",
                      isNew
                        ? "border-primary bg-primary-container/10 shadow-lg shadow-primary/20"
                        : "border-outline-variant/30 bg-surface-container-low"
                    )}
                  >
                    <div className="flex gap-3">
                      <BoardAvatar picture={m.profilePic} name={m.authorName} />
                      <div className="flex-1 min-w-0">
                        <div className="flex flex-wrap items-baseline gap-2 mb-1">
                          <span className="font-bold text-on-surface">{m.authorName}</span>
                          <span className="text-xs text-on-surface-variant">{formatDate(m.createdAt)}</span>
                          <span className="text-xs font-mono text-primary">⚡ {m.satsPaid} sats</span>
                        </div>
                        <p className="text-on-surface whitespace-pre-wrap break-words">{m.content}</p>
                        <div className="flex flex-wrap gap-2 mt-4">
                          {m.pubkey && user ? (
                            <button
                              type="button"
                              onClick={() => bumpLike(m)}
                              className="inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm bg-surface-container-high text-on-surface hover:bg-surface-container transition-colors"
                            >
                              <Heart size={16} className="text-red-400" />
                              {likes}
                            </button>
                          ) : m.pubkey ? (
                            <span className="inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm bg-surface-container-high text-on-surface-variant">
                              <Heart size={16} className="text-red-400/70" />
                              {likes}
                            </span>
                          ) : null}
                          <button
                            type="button"
                            onClick={() => handleZap(m)}
                            className="inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm bg-surface-container-high text-on-surface hover:bg-surface-container transition-colors"
                          >
                            <Zap size={16} className="text-amber-400" />
                            Zap
                          </button>
                        </div>
                      </div>
                    </div>
                  </li>
                );
              })}
            </ul>
            {messages.length === 0 && (
              <p className="text-on-surface-variant text-center py-12">No messages yet — be the first.</p>
            )}
          </section>
        </div>
      </div>
      <Footer />
    </>
  );
}
