"use client";

/**
 * AppPartnerThread — native conversation thread overlay.
 * Gejt na URL `/portal/poruke?thread=<id>` (query-param routing).
 * Lista poruka + input za novu poruku + back na inbox.
 */

import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";

import { nativeHaptic } from "@/components/native/CapacitorBootstrap";
import { ArrowRightIcon } from "@/components/native/PartnerIcons";
import { trackScreen } from "@/lib/native/analytics";
import { getLocalePrefix, type Locale } from "@/lib/i18n/i18n";
import { useAppVariant } from "@/lib/native/app-variant";
import { usePartnerPreview } from "@/lib/native/preview-partner";
import { usePoll } from "@/lib/native/use-poll";

type Message = {
  id: string;
  body: string;
  isMine: boolean;
  createdAt: string;
};

type Payload = {
  conversation: { id: string; contextTitle: string | null; contextPath: string | null };
  messages: Message[];
};

function useIsNative(): boolean | null {
  const [n, setN] = useState<boolean | null>(null);
  useEffect(() => {
    let d = false;
    (async () => {
      try {
        const { Capacitor } = await import("@capacitor/core");
        if (!d) setN(Capacitor.isNativePlatform());
      } catch {
        if (!d) setN(false);
      }
    })();
    return () => {
      d = true;
    };
  }, []);
  return n;
}

function isMessagesPath(p: string, prefix: string): boolean {
  const x = prefix && p.startsWith(prefix) ? p.slice(prefix.length) : p;
  return (x.replace(/\/+$/, "") || "/") === "/portal/poruke";
}

function fmtTime(iso: string): string {
  try {
    return new Date(iso).toLocaleTimeString("sr-RS", {
      hour: "2-digit",
      minute: "2-digit",
    });
  } catch {
    return iso.slice(11, 16);
  }
}

export function AppPartnerThread({
  locale,
  dictionary,
}: {
  locale: Locale;
  dictionary: Record<string, string>;
}) {
  const native = useIsNative();
  const variant = useAppVariant();
  const preview = usePartnerPreview();
  const pathname = usePathname();
  const router = useRouter();
  const search = useSearchParams();
  const prefix = getLocalePrefix(locale);
  const threadId = search.get("thread");
  const active =
    (preview.enabled && preview.screen === "thread") ||
    (isMessagesPath(pathname, prefix) &&
      !!threadId &&
      native === true &&
      variant === "partner");

  const [data, setData] = useState<Payload | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const [draft, setDraft] = useState("");
  const [sending, setSending] = useState(false);
  const scrollerRef = useRef<HTMLDivElement | null>(null);
  // Da li je korisnik pri dnu? Meri se na skrol, PRE nego što stignu novi
  // podaci — posle re-rendera je scrollHeight već narastao pa je merenje lažno.
  const nearBottomRef = useRef(true);

  const t = (k: string, fb: string) => dictionary[k] ?? fb;

  const load = useCallback(async () => {
    setLoading(true);
    setError(false);
    try {
      const url = preview.enabled
        ? "/api/app/partner/demo?kind=thread"
        : `/api/app/partner/thread/${threadId}`;
      const res = await fetch(url, { cache: "no-store" });
      if (res.status === 401 && !preview.enabled) {
        window.location.assign(`${prefix}/portal/login`);
        return;
      }
      if (!res.ok) {
        setError(true);
        return;
      }
      setData((await res.json()) as Payload);
    } catch {
      setError(true);
    } finally {
      setLoading(false);
    }
  }, [prefix, preview.enabled, threadId]);

  useEffect(() => {
    if (active && (threadId || preview.enabled)) void load();
  }, [active, threadId, load, preview.enabled]);

  useEffect(() => {
    if (active) trackScreen("partner_thread");
  }, [active]);

  // Skrol na dno SAMO ako je korisnik ionako bio pri dnu. Ranije je skakalo
  // na svaku promenu — sa pollingom bi to otimalo poziciju svakome ko je
  // odskrolovao gore da pročita stariji deo razgovora.
  useEffect(() => {
    if (!data) return;
    const el = scrollerRef.current;
    if (el && nearBottomRef.current) el.scrollTop = el.scrollHeight;
  }, [data]);

  usePoll(load, 7_000, active && !preview.enabled);

  const send = useCallback(async () => {
    const body = draft.trim();
    if (!body || sending) return;
    setSending(true);
    try {
      if (preview.enabled) {
        const fake: Message = {
          id: `local-${Date.now()}`,
          body,
          isMine: true,
          createdAt: new Date().toISOString(),
        };
        setData((d) => (d ? { ...d, messages: [...d.messages, fake] } : d));
        setDraft("");
        return;
      }
      const res = await fetch(`/api/app/partner/thread/${threadId}`, {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ body }),
      });
      if (!res.ok) return;
      const j = (await res.json()) as { message: Message };
      setData((d) => (d ? { ...d, messages: [...d.messages, j.message] } : d));
      setDraft("");
    } finally {
      setSending(false);
    }
  }, [draft, sending, threadId, preview.enabled]);

  if (!active) return null;

  return (
    <div className="apppartner-root" role="region" aria-label="Razgovor">
      <div className="apppartner-hero apppartner-hero-compact">
        <div className="apppartner-hero-text">
          <button
            type="button"
            className="apppartner-back"
            onClick={() => {
              void nativeHaptic();
              router.push(`${prefix}/portal/poruke`);
            }}
            aria-label={t("common.back", "Nazad")}
          >
            ←
          </button>
          <h1 className="apppartner-title">
            {data?.conversation.contextTitle ??
              t("partner.thread.title", "Razgovor")}
          </h1>
        </div>
      </div>

      <div
        className="apppartner-thread-body"
        ref={scrollerRef}
        onScroll={(e) => {
          const el = e.currentTarget;
          nearBottomRef.current =
            el.scrollHeight - el.scrollTop - el.clientHeight < 120;
        }}
      >
        {loading && !data ? (
          <div className="apppartner-skel-grid" aria-hidden>
            {Array.from({ length: 3 }).map((_, i) => (
              <div key={i} className="apppartner-skel apppartner-skel-row" />
            ))}
          </div>
        ) : error ? (
          <div className="apppartner-empty">
            <p>{t("partner.thread.err", "Trenutno ne mogu da učitam razgovor.")}</p>
            <button
              type="button"
              className="apppartner-btn-primary"
              onClick={() => {
                void nativeHaptic();
                void load();
              }}
            >
              {t("common.retry", "Pokušaj ponovo")}
            </button>
          </div>
        ) : data && data.messages.length > 0 ? (
          <ul className="apppartner-msg-list">
            {data.messages.map((m) => (
              <li
                key={m.id}
                className={`apppartner-msg ${m.isMine ? "apppartner-msg-mine" : "apppartner-msg-theirs"}`}
              >
                <span className="apppartner-msg-body">{m.body}</span>
                <span className="apppartner-msg-time">{fmtTime(m.createdAt)}</span>
              </li>
            ))}
          </ul>
        ) : (
          <p className="apppartner-empty-line">
            {t("partner.thread.empty", "Nema poruka još. Pošalji prvu.")}
          </p>
        )}
      </div>

      <div className="apppartner-compose">
        <textarea
          className="apppartner-input apppartner-textarea apppartner-compose-input"
          rows={2}
          placeholder={t("partner.thread.placeholder", "Napiši poruku…")}
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) {
              e.preventDefault();
              void send();
            }
          }}
        />
        <button
          type="button"
          className="apppartner-compose-send"
          disabled={!draft.trim() || sending}
          aria-label={t("partner.thread.send", "Pošalji")}
          onClick={() => {
            void nativeHaptic();
            void send();
          }}
        >
          <ArrowRightIcon />
        </button>
      </div>
    </div>
  );
}

export default AppPartnerThread;
