// src/pages/Notif.jsx
// ✅ همه alert/پیغام‌ها → Toast
// ✅ toast برای: دریافت موفق/ناموفق، خوانده‌شدن تکی، خوانده‌شدن همه، خطاها، و حالت‌های لازم (مثل نبودن مورد خوانده‌نشده)
// ✅ دکمه بروزرسانی ضد اسپم شد: inFlight lock + cooldown + countdown

import React, { useEffect, useMemo, useRef, useState } from "react";
import { Axiosinstance } from "../services/auth/Axiosinstance";
import { TbCheck, TbClock, TbSearch, TbX, TbPointFilled } from "react-icons/tb";
import { LuRefreshCcw } from "react-icons/lu";
import { FaRegEnvelope } from "react-icons/fa";
import { useToast } from "../components/ToastProvider";

/* ---------------- helpers ---------------- */
function cn(...a) {
  return a.filter(Boolean).join(" ");
}

function toFa(v) {
  try {
    return String(v).toLocaleString("fa-IR");
  } catch {
    return v;
  }
}

function fmtDateTime(iso) {
  if (!iso) return "-";
  try {
    const d = new Date(iso);
    return d.toLocaleString("fa-IR", {
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
    });
  } catch {
    return iso;
  }
}

const CARD =
  "rounded-2xl shadow border border-black/10 dark:border-white/10 bg-white/70 dark:bg-white/5 backdrop-blur-sm";
const SOFT =
  "rounded-2xl shadow border border-black/10 dark:border-white/10 dark:bg-[#A1E3F919] bg-[#A1E3F919]";
const INPUT_BASE =
  "w-full dark:bg-[#A1E3F919] bg-[#A1E3F980] rounded-xl grid relative items-center";
const INPUT =
  "h-11 px-4 w-full outline-0 focus:outline-0 rounded-xl bg-transparent text-black dark:text-white placeholder:text-black/50 dark:placeholder:text-white/50";

function normalizeArray(data) {
  if (Array.isArray(data)) return data;
  if (Array.isArray(data?.results)) return data.results;
  if (Array.isArray(data?.data)) return data.data;
  if (Array.isArray(data?.notifications)) return data.notifications;
  return [];
}

const getErrMsg = (e, fallback = "خطا") => {
  const d = e?.response?.data;
  if (!d) return e?.message || fallback;
  if (typeof d === "string") return d;
  if (d.detail) return d.detail;
  try {
    const first = typeof d === "object" ? Object.values(d)?.flat?.()?.[0] : null;
    return first || fallback;
  } catch {
    return fallback;
  }
};

/* ---------------- Main ---------------- */
function Notif() {
  const { success, error: toastError, info, warning } = useToast();

  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);

  // UI state
  const [q, setQ] = useState("");
  const [tab, setTab] = useState("all"); // all | unread | read
  const [sort, setSort] = useState("new"); // new | old
  const [readingId, setReadingId] = useState(null);
  const [markingAll, setMarkingAll] = useState(false);

  /* ==================== ✅ Refresh Guards (anti-spam) ==================== */
  const REFRESH_COOLDOWN_MS = 3000;
  const refreshInFlightRef = useRef(false);
  const refreshLastAtRef = useRef(0);
  const refreshToastLockRef = useRef(0);
  const [refreshLeftMs, setRefreshLeftMs] = useState(0);

  useEffect(() => {
    if (refreshLeftMs <= 0) return;
    const t = setInterval(() => {
      const left = Math.max(
        0,
        REFRESH_COOLDOWN_MS - (Date.now() - refreshLastAtRef.current)
      );
      setRefreshLeftMs(left);
      if (left <= 0) clearInterval(t);
    }, 120);
    return () => clearInterval(t);
  }, [refreshLeftMs]);
  /* ====================================================================== */

  const fetchNotifications = async (isRefresh = false, { silent = false } = {}) => {
    isRefresh ? setRefreshing(true) : setLoading(true);

    try {
      const res = await Axiosinstance.get("accounts/notifications/");
      setItems(normalizeArray(res?.data));
      if (!silent) info("نوتیفیکیشن‌ها بروزرسانی شد.", { title: "نوتیفیکیشن‌ها" });
    } catch (e) {
      toastError(getErrMsg(e, "خطا در دریافت نوتیفیکیشن‌ها"), {
        title: "نوتیفیکیشن‌ها",
      });
    } finally {
      isRefresh ? setRefreshing(false) : setLoading(false);
    }
  };

  // ✅ دکمه بروزرسانیِ درست
  const guardedRefresh = async () => {
    const now = Date.now();

    if (refreshInFlightRef.current || loading || refreshing) {
      if (now - refreshToastLockRef.current > 900) {
        refreshToastLockRef.current = now;
        info("در حال بروزرسانی...", { title: "نوتیفیکیشن‌ها" });
      }
      return;
    }

    const diff = now - refreshLastAtRef.current;
    if (diff < REFRESH_COOLDOWN_MS) {
      const left = REFRESH_COOLDOWN_MS - diff;
      setRefreshLeftMs(left);

      if (now - refreshToastLockRef.current > 900) {
        refreshToastLockRef.current = now;
        info(`لطفاً ${Math.ceil(left / 1000)} ثانیه صبر کن.`, {
          title: "بروزرسانی",
        });
      }
      return;
    }

    refreshInFlightRef.current = true;
    refreshLastAtRef.current = now;
    setRefreshLeftMs(REFRESH_COOLDOWN_MS);

    try {
      await fetchNotifications(true, { silent: false });
    } finally {
      refreshInFlightRef.current = false;
    }
  };

  useEffect(() => {
    fetchNotifications(false, { silent: true });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const computed = useMemo(() => {
    const query = q.trim().toLowerCase();

    const normalized = (items || []).map((n) => {
      const created = n?.created_at ? new Date(n.created_at).getTime() : 0;
      return {
        ...n,
        _createdTs: created,
        _blob: `${n?.title || ""} ${n?.message || ""}`.toLowerCase(),
      };
    });

    let list = normalized;

    if (tab === "unread") list = list.filter((n) => !n?.is_read);
    if (tab === "read") list = list.filter((n) => !!n?.is_read);

    if (query) list = list.filter((n) => n._blob.includes(query));

    list.sort((a, b) =>
      sort === "new" ? b._createdTs - a._createdTs : a._createdTs - b._createdTs
    );

    const total = normalized.length;
    const unread = normalized.filter((n) => !n?.is_read).length;
    const read = total - unread;

    return { list, total, unread, read };
  }, [items, q, tab, sort]);

  const markRead = async (id) => {
    if (!id) return;

    // optimistic
    setItems((prev) =>
      (prev || []).map((n) =>
        String(n?.id) === String(id) ? { ...n, is_read: true } : n
      )
    );
    setReadingId(String(id));

    try {
      await Axiosinstance.post(`accounts/notifications/${id}/read/`);
      success("نوتیفیکیشن خوانده شد ✅", { title: "نوتیفیکیشن‌ها" });

      // سبک و مطمئن: refetch
      fetchNotifications(true, { silent: true });
    } catch (e) {
      // rollback
      setItems((prev) =>
        (prev || []).map((n) =>
          String(n?.id) === String(id) ? { ...n, is_read: false } : n
        )
      );
      toastError(getErrMsg(e, "خطا در خوانده‌کردن نوتیفیکیشن"), {
        title: "نوتیفیکیشن‌ها",
      });
    } finally {
      setReadingId(null);
    }
  };

  const markAllUnread = async () => {
    const unreadIds = (items || [])
      .filter((n) => !n?.is_read)
      .map((n) => n?.id)
      .filter(Boolean);

    if (unreadIds.length === 0) {
      warning("مورد خوانده‌نشده‌ای وجود ندارد.", { title: "نوتیفیکیشن‌ها" });
      return;
    }

    setMarkingAll(true);

    // optimistic
    setItems((prev) => (prev || []).map((n) => ({ ...n, is_read: true })));

    try {
      await Promise.all(
        unreadIds.map((id) =>
          Axiosinstance.post(`accounts/notifications/${id}/read/`)
        )
      );
      success("همه نوتیفیکیشن‌ها خوانده شد ✅", { title: "نوتیفیکیشن‌ها" });

      fetchNotifications(true, { silent: true });
    } catch (e) {
      toastError(getErrMsg(e, "خطا در خوانده‌کردن همه موارد"), {
        title: "نوتیفیکیشن‌ها",
      });
      // امن‌ترین: refetch
      fetchNotifications(true, { silent: true });
    } finally {
      setMarkingAll(false);
    }
  };

  const refreshDisabled = loading || refreshing || refreshLeftMs > 0;
  const refreshLabel =
    refreshing
      ? "درحال بروزرسانی..."
      : refreshLeftMs > 0
      ? `بروزرسانی`
      : "بروزرسانی";

  return (
    <div className="w-full dark:text-white">
      <div className="mb-5 rounded-2xl border border-black/10 dark:border-white/10 bg-[#A1E3F910] shadow dark:bg-[#A1E3F910] p-3 sm:p-4">
        <div className="flex flex-col lg:flex-row gap-3 lg:items-center lg:justify-between min-w-0">
          <div className="min-w-0">
            <h1 className="text-lg sm:text-xl font-extrabold">
              نوتیفیکیشن‌ها
            </h1>
            <p className="text-xs sm:text-sm text-black/60 dark:text-white/70 truncate">
              کل: <b>{toFa(computed.total)}</b> • خوانده‌نشده:{" "}
              <b
                className={
                  computed.unread ? "text-red-600 dark:text-red-300" : ""
                }
              >
                {toFa(computed.unread)}
              </b>
            </p>
          </div>

          <div className="flex items-center gap-2 w-full lg:w-auto">
            <button
              type="button"
              onClick={guardedRefresh}
              disabled={refreshDisabled}
              className="px-3 py-2 rounded-xl shadow bg-white dark:bg-[#16325b] border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 text-sm inline-flex items-center gap-2 disabled:opacity-60"
              title={
                refreshLeftMs > 0
                  ? `تا ${Math.ceil(refreshLeftMs / 1000)} ثانیه دیگر`
                  : "بروزرسانی"
              }
            >
              <LuRefreshCcw
                className={cn(
                  "w-4 h-4 text-[#43BEFF] dark:text-white",
                  refreshing ? "animate-spin" : ""
                )}
              />
              {refreshLabel}
            </button>

            <button
              type="button"
              onClick={markAllUnread}
              disabled={markingAll || computed.unread === 0}
              className="px-3 py-2 rounded-xl shadow bg-white dark:bg-[#16325b] border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 text-sm inline-flex items-center gap-2 disabled:opacity-60"
              title="خوانده شد (همه)"
            >
              <FaRegEnvelope
                className={cn(
                  "w-4 h-4 text-[#43BEFF] dark:text-white",
                  markingAll ? "animate-spin" : ""
                )}
              />
              {markingAll ? "در حال انجام..." : "خوانده شد (همه)"}
            </button>
          </div>
        </div>
      </div>

      {/* Header */}
      <div className={cn(CARD, "p-4 md:p-5 mb-6")}>
        {/* Filters */}
        <div className="grid lg:grid-cols-3 gap-3">
          {/* search */}
          <div className={cn(INPUT_BASE, "lg:col-span-2")}>
            <div className="absolute right-3 top-1/2 -translate-y-1/2 opacity-70">
              <TbSearch className="w-5 h-5" />
            </div>
            <input
              className={cn(INPUT, "pr-11")}
              placeholder="جستجو در عنوان یا پیام..."
              value={q}
              onChange={(e) => setQ(e.target.value)}
            />
          </div>

          {/* sort + tabs */}
          <div className="flex items-center gap-2">
            <Segment value={tab} onChange={setTab} />
            <select
              value={sort}
              onChange={(e) => setSort(e.target.value)}
              className="h-11 px-3 rounded-xl shadow bg-[#A1E3F980] dark:bg-[#A1E3F919] border border-black/10 dark:border-white/10 text-sm outline-0"
            >
              <option value="new">جدیدترین</option>
              <option value="old">قدیمی‌ترین</option>
            </select>
          </div>
        </div>
      </div>

      {/* List */}
      <div className={cn(CARD, "p-4 md:p-5")}>
        <div className={cn(SOFT, "overflow-hidden")}>
          {loading ? (
            <div className="p-4 space-y-3">
              {[1, 2, 3, 4, 5].map((i) => (
                <div
                  key={i}
                  className="h-16 rounded-2xl shadow bg-black/5 dark:bg-white/10 animate-pulse"
                />
              ))}
            </div>
          ) : computed.list.length === 0 ? (
            <div className="py-12 text-center text-black/50 dark:text-white/60 text-sm">
              چیزی برای نمایش وجود ندارد.
            </div>
          ) : (
            computed.list.map((n, idx) => (
              <React.Fragment key={String(n?.id ?? idx)}>
                <NotifRow
                  n={n}
                  loading={String(readingId) === String(n?.id)}
                  onMarkRead={() => markRead(n?.id)}
                />
                {idx !== computed.list.length - 1 && <Divider />}
              </React.Fragment>
            ))
          )}
        </div>
      </div>
    </div>
  );
}

function Divider() {
  return <hr className="border-b border-black/10 dark:border-white/10" />;
}

function Segment({ value, onChange }) {
  const base = "h-11 px-3 rounded-xl shadow border text-xs sm:text-sm transition";
  const active = "bg-[#43BEFF] text-white border-transparent";
  const idle =
    "bg-[#A1E3F980] dark:bg-[#A1E3F919] border-black/10 dark:border-white/10 text-black dark:text-white hover:bg-[#43BEFF40]";

  return (
    <div className="flex items-center gap-2 flex-1">
      <button
        type="button"
        onClick={() => onChange("all")}
        className={cn(base, value === "all" ? active : idle)}
      >
        همه
      </button>
      <button
        type="button"
        onClick={() => onChange("unread")}
        className={cn(base, value === "unread" ? active : idle)}
      >
        خوانده‌نشده
      </button>
      <button
        type="button"
        onClick={() => onChange("read")}
        className={cn(base, value === "read" ? active : idle)}
      >
        خوانده‌شده
      </button>
    </div>
  );
}

function NotifRow({ n, onMarkRead, loading }) {
  const isRead = !!n?.is_read;

  return (
    <div
      className={cn(
        "p-4 flex items-start gap-3",
        !isRead ? "bg-[#43BEFF10]" : "bg-transparent"
      )}
    >
      <div className="w-10 h-10 rounded-xl shadow bg-white/70 dark:bg-white/10 border border-black/10 dark:border-white/10 flex items-center justify-center shrink-0 relative">
        {!isRead && (
          <TbPointFilled className="absolute -top-2 -left-2 w-5 h-5 text-[#43BEFF]" />
        )}
        {isRead ? (
          <TbCheck className="h-5 w-5 text-white bg-green-600 p-1 rounded-full" />
        ) : (
          <TbX className="h-5 w-5 text-white bg-[#001f3f] p-1 rounded-full" />
        )}
      </div>

      <div className="flex-1 min-w-0">
        <div className="flex items-start justify-between gap-3">
          <div className="min-w-0">
            <div className="text-sm font-extrabold text-black dark:text-white truncate">
              {n?.title || "بدون عنوان"}
            </div>
            <div className="mt-1 text-xs text-black/60 dark:text-white/70 leading-5 whitespace-pre-line">
              {n?.message || "-"}
            </div>
          </div>

          <div className="shrink-0 text-[11px] text-black/50 dark:text-white/60 flex items-center gap-1">
            <TbClock className="w-4 h-4" />
            {fmtDateTime(n?.created_at)}
          </div>
        </div>

        {!isRead && (
          <div className="mt-3 flex justify-end">
            <button
              type="button"
              onClick={onMarkRead}
              disabled={loading}
              className="text-xs px-3 py-1.5 rounded-full bg-[#43BEFF] hover:bg-[#34b6ff] text-white transition disabled:opacity-60"
            >
              {loading ? "..." : "خوانده شد"}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

export default Notif;
