import React, { useEffect, useRef, useState } from "react";
import { Axiosinstance } from "../services/auth/Axiosinstance";
import { useToast } from "../components/ToastProvider";

import PageHeader from "../components/ui/PageHeader";
import Button from "../components/ui/Button";

import { LuRefreshCcw } from "react-icons/lu";

import useCooldownAction from "../hooks/useCooldownAction";
import { getErrMsg } from "../utils/account";
import { normalizeHostname } from "../utils/domains";

import DomainCreateCard from "../components/domains/DomainCreateCard";
import DomainInstructionsCard from "../components/domains/DomainInstructionsCard";
import DomainsListCard from "../components/domains/DomainsListCard";

export default function Domains() {
  const { success, error: toastError, info } = useToast();

  const [domains, setDomains] = useState([]);
  const [loading, setLoading] = useState(true);

  // create
  const [hostname, setHostname] = useState("");
  const [creating, setCreating] = useState(false);

  // selected
  const [selected, setSelected] = useState(null);

  // page error
  const [error, setError] = useState("");

  /* ==================== Verify Guard per domain ==================== */
  const VERIFY_COOLDOWN_MS = 8000;
  const verifyInFlightRef = useRef(new Set());
  const verifyLastAtRef = useRef(new Map());
  const [, forceTick] = useState(0);

  useEffect(() => {
    const t = setInterval(() => forceTick((x) => x + 1), 500);
    return () => clearInterval(t);
  }, []);

  const verifyInFlight = (id) => verifyInFlightRef.current.has(id);

  const verifyCooldownLeftSec = (id) => {
    const last = verifyLastAtRef.current.get(id) || 0;
    const diff = Date.now() - last;
    if (diff >= VERIFY_COOLDOWN_MS) return 0;
    return Math.ceil((VERIFY_COOLDOWN_MS - diff) / 1000);
  };

  /* ==================== Patch Busy per domain ==================== */
  const patchBusyRef = useRef(new Set());
  const [, forcePatchTick] = useState(0);

  const setPatchBusy = (id, value) => {
    if (!id) return;
    if (value) patchBusyRef.current.add(id);
    else patchBusyRef.current.delete(id);
    forcePatchTick((x) => x + 1);
  };

  const patchBusy = (id) => patchBusyRef.current.has(id);

  /* ==================== Delete Busy per domain ==================== */
  const deleteBusyRef = useRef(new Set());
  const [, forceDeleteBusyTick] = useState(0);

  const setDeleteBusy = (id, value) => {
    if (!id) return;
    if (value) deleteBusyRef.current.add(id);
    else deleteBusyRef.current.delete(id);
    forceDeleteBusyTick((x) => x + 1);
  };

  const deleteBusy = (id) => deleteBusyRef.current.has(id);

  /* ==================== Delete Arm Guard per domain ==================== */
  const DELETE_ARM_MS = 5000;
  const deleteArmedAtRef = useRef(new Map());
  const [, forceDeleteArmTick] = useState(0);

  useEffect(() => {
    const t = setInterval(() => forceDeleteArmTick((x) => x + 1), 500);
    return () => clearInterval(t);
  }, []);

  const armDelete = (id) => {
    deleteArmedAtRef.current.set(id, Date.now());
    forceDeleteArmTick((x) => x + 1);
  };

  const clearDeleteArm = (id) => {
    deleteArmedAtRef.current.delete(id);
    forceDeleteArmTick((x) => x + 1);
  };

  const deleteArmedLeftSec = (id) => {
    const at = deleteArmedAtRef.current.get(id) || 0;
    if (!at) return 0;
    const diff = Date.now() - at;
    if (diff >= DELETE_ARM_MS) return 0;
    return Math.ceil((DELETE_ARM_MS - diff) / 1000);
  };

  const isDeleteArmed = (id) => deleteArmedLeftSec(id) > 0;

  const copy = async (text, label = "متن") => {
    if (!text) {
      toastError("چیزی برای کپی وجود ندارد.", { title: "کپی" });
      return false;
    }

    try {
      if (navigator?.clipboard?.writeText) {
        await navigator.clipboard.writeText(String(text));
        success(`${label} کپی شد ✅`, { title: "کپی" });
        return true;
      }
    } catch {}

    try {
      const ta = document.createElement("textarea");
      ta.value = String(text);
      ta.style.position = "fixed";
      ta.style.left = "-9999px";
      document.body.appendChild(ta);
      ta.focus();
      ta.select();
      const ok = document.execCommand("copy");
      document.body.removeChild(ta);

      if (ok) {
        success(`${label} کپی شد ✅`, { title: "کپی" });
      } else {
        toastError("کپی انجام نشد.", { title: "کپی" });
      }
      return ok;
    } catch {
      toastError("کپی انجام نشد. اجازه Clipboard را بررسی کن.", { title: "کپی" });
      return false;
    }
  };

  const fetchDomains = async ({ toast = false, silent = false } = {}) => {
    if (!silent) setLoading(true);
    setError("");

    try {
      const res = await Axiosinstance.get("storage/domains/");
      const list = Array.isArray(res.data) ? res.data : [];

      list.sort(
        (a, b) =>
          new Date(b?.created_at || 0).getTime() -
          new Date(a?.created_at || 0).getTime()
      );

      setDomains(list);

      setSelected((prev) => {
        if (!prev?.id) return prev;
        const updated = list.find((x) => x?.id === prev.id);
        return updated || null;
      });

      if (toast) {
        success("دامنه‌ها بروزرسانی شد.", { title: "دامنه اختصاصی" });
      }

      return list;
    } catch (e) {
      const msg = getErrMsg(e, "خطا در دریافت دامنه‌ها");
      setError(msg);
      if (toast) toastError(msg, { title: "خطا" });
      return null;
    } finally {
      if (!silent) setLoading(false);
    }
  };

  const refresh = useCooldownAction({
    cooldownMs: 3000,
    toastGapMs: 900,
    isBusy: loading,
    busyMessage: "در حال بروزرسانی هستیم...",
    busyToast: info,
    title: "دامنه‌ها",
    onRun: async () => {
      await fetchDomains({ toast: true });
    },
  });

  const createDomain = async () => {
    const hn = normalizeHostname(hostname);

    if (!hn) {
      toastError("hostname را وارد کن (مثلاً: netnest.org)", { title: "ثبت دامنه" });
      return;
    }

    setCreating(true);
    try {
      const res = await Axiosinstance.post("storage/domains/", { hostname: hn });
      const data = res?.data;

      success("دامنه ثبت شد ✅", { title: "دامنه اختصاصی" });
      info("حالا رکورد TXT را در DNS بساز و بعد Verify بزن.", { title: "مرحله بعد" });

      setDomains((prev) => [data, ...(prev || [])]);
      setSelected(data);
      setHostname("");
    } catch (e) {
      toastError(getErrMsg(e, "ثبت دامنه ناموفق بود."), { title: "ثبت دامنه" });
    } finally {
      setCreating(false);
    }
  };

  const verifyDomain = async (domain) => {
    const id = domain?.id;
    if (!id) return;

    if (verifyInFlightRef.current.has(id)) {
      info("در حال Verify هستیم...", { title: "Verify" });
      return;
    }

    const last = verifyLastAtRef.current.get(id) || 0;
    const diff = Date.now() - last;

    if (diff < VERIFY_COOLDOWN_MS) {
      const left = Math.ceil((VERIFY_COOLDOWN_MS - diff) / 1000);
      info(`لطفاً ${left} ثانیه صبر کن و دوباره Verify بزن.`, { title: "Verify" });
      return;
    }

    verifyInFlightRef.current.add(id);
    verifyLastAtRef.current.set(id, Date.now());
    forceTick((x) => x + 1);

    try {
      await Axiosinstance.post(`storage/domains/${id}/verify/`);

      success("دامنه با موفقیت Verify شد ✅", { title: "Verify" });

      await fetchDomains({ silent: true });
    } catch (e) {
      const status = e?.response?.status;

      if (status === 404) {
        toastError(
          "این دامنه پیدا نشد (404). احتمالاً برای اکانت شما نیست یا حذف شده.",
          { title: "Verify" }
        );
      } else if (status === 400) {
        toastError(
          getErrMsg(e, "DNS lookup failed یا TXT record match نیست."),
          { title: "Verify" }
        );
        info("مطمئن شو TXT دقیقاً درست ساخته شده و چند دقیقه برای انتشار DNS صبر کن.", {
          title: "راهنما",
        });
      } else {
        toastError(getErrMsg(e, "Verify ناموفق بود."), { title: "Verify" });
      }
    } finally {
      verifyInFlightRef.current.delete(id);
      forceTick((x) => x + 1);
    }
  };

  const handleToggleActive = async (domain) => {
    const id = domain?.id;
    if (!id || patchBusy(id)) return;

    setPatchBusy(id, true);
    try {
      await Axiosinstance.post(`storage/domains/${id}/activate/`);

      success(
        domain?.is_active ? "دامنه فعال است ✅" : "دامنه فعال شد ✅",
        { title: "وضعیت دامنه" }
      );

      await fetchDomains({ silent: true });
    } catch (e) {
      toastError(getErrMsg(e, "تغییر وضعیت دامنه ناموفق بود."), {
        title: "وضعیت دامنه",
      });
    } finally {
      setPatchBusy(id, false);
    }
  };

  const handleTogglePrimary = async (domain) => {
    const id = domain?.id;
    const isPrimary = domain?.primary === true || domain?.is_primary === true;

    if (!id || patchBusy(id) || isPrimary) return;

    setPatchBusy(id, true);
    try {
      // درخواست تغییر دامنه به پرایمری
      await Axiosinstance.post(`storage/domains/${id}/primary/`);

      // همزمان درخواست فعال‌سازی دامنه
      await Axiosinstance.post(`storage/domains/${id}/activate/`);

      success("دامنه اصلی بروزرسانی شد ✅", { title: "دامنه اصلی" });

      await fetchDomains({ silent: true });
    } catch (e) {
      toastError(getErrMsg(e, "تغییر دامنه اصلی ناموفق بود."), {
        title: "دامنه اصلی",
      });
    } finally {
      setPatchBusy(id, false);
    }
  };

  const handleDelete = async (domain) => {
    const id = domain?.id;
    if (!id || deleteBusy(id)) return;

    if (!isDeleteArmed(id)) {
      armDelete(id);
      info("برای حذف، دوباره روی دکمه حذف بزن.", { title: "تأیید حذف" });
      return;
    }

    setDeleteBusy(id, true);
    try {
      await Axiosinstance.delete(`storage/domains/${id}/`);

      success("دامنه حذف شد ✅", { title: "حذف دامنه" });

      clearDeleteArm(id);

      setDomains((prev) => (prev || []).filter((x) => x?.id !== id));
      setSelected((prev) => (prev?.id === id ? null : prev));
    } catch (e) {
      toastError(getErrMsg(e, "حذف دامنه ناموفق بود."), { title: "حذف دامنه" });
    } finally {
      setDeleteBusy(id, false);
    }
  };

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

  const refreshLabel = loading ? "درحال بروزرسانی..." : "بروزرسانی";
  const refreshTitle =
    refresh.leftMs > 0
      ? `تا ${Math.ceil(refresh.leftMs / 1000)} ثانیه دیگر`
      : "بروزرسانی لیست دامنه‌ها";

  return (
    <div className="dark:text-white w-full space-y-6">
      <PageHeader
        title="دامنه اختصاصی"
        subtitle="ثبت hostname، دریافت توکن، ساخت TXT در DNS و تایید"
        right={
          <Button
            type="button"
            onClick={refresh.run}
            disabled={refresh.disabled}
            variant="outline"
            size="lg"
            title={refreshTitle}
            leftIcon={
              <LuRefreshCcw
                className={`w-4 h-4 text-[#43BEFF] dark:text-white ${
                  loading ? "animate-spin" : ""
                }`}
              />
            }
          >
            {refreshLabel}
          </Button>
        }
      />

      <DomainCreateCard
        hostname={hostname}
        setHostname={setHostname}
        creating={creating}
        onCreate={createDomain}
      />

      {selected ? (
        <DomainInstructionsCard
          selected={selected}
          onVerify={() => verifyDomain(selected)}
          onCopy={copy}
        />
      ) : null}

      {!loading && !!error ? (
        <div className="p-4 rounded-xl shadow border border-red-500/30 bg-red-500/10 text-sm">
          {error}
        </div>
      ) : null}

      <DomainsListCard
        loading={loading}
        domains={domains}
        selectedId={selected?.id || null}
        onSelectDomain={setSelected}
        verifyLeftSec={verifyCooldownLeftSec}
        verifyInFlight={verifyInFlight}
        onCopyTxtName={() => copy(`_netnest-verify`, "TXT Name")}
        onCopyTxtValue={(d) => copy(d?.verification_token, "TXT Value")}
        onVerify={verifyDomain}
        onToggleActive={handleToggleActive}
        onTogglePrimary={handleTogglePrimary}
        onDelete={handleDelete}
        patchBusy={patchBusy}
        deleteBusy={deleteBusy}
        deleteArmedLeftSec={deleteArmedLeftSec}
      />
    </div>
  );
}
