"use client";
/**
 * طبقة توافق react-router-dom ← Next.js App Router
 * ------------------------------------------------------------------
 * كل الاستيرادات `from "react-router-dom"` في الشيفرة الأصلية تُحوَّل إلى
 * هذا الملف عبر alias في tsconfig.json و next.config.mjs، فتبقى مكوّنات
 * الصفحات الأصلية كما هي حرفياً دون تعديل في منطقها أو تصميمها.
 *
 * الواجهات المدعومة (كل ما يستخدمه المشروع الأصلي فعلياً):
 *   Link, NavLink, Navigate, Outlet, useNavigate, useLocation,
 *   useParams, useSearchParams
 *
 * location.state: يحفظه React Router داخل history.state؛ هنا يُحفظ في
 * sessionStorage مفتاحاً بالمسار المستهدف، فيبقى متاحاً بعد التنقل وبعد
 * إعادة تحميل الصفحة تماماً كما في السلوك الأصلي.
 */
import NextLink from "next/link";
import { COURSE_BASE, parseCourseParam } from "@/lib/course-url";
import {
    useParams as useNextParams,
    usePathname,
    useRouter,
    useSearchParams as useNextSearchParams,
} from "next/navigation";
import React, {
    createContext,
    forwardRef,
    useCallback,
    useContext,
    useEffect,
    useMemo,
    useState,
} from "react";

/* ------------------------------------------------------------------ */
/* أدوات داخلية                                                         */
/* ------------------------------------------------------------------ */

type To = string | { pathname?: string; search?: string; hash?: string };

const STATE_PREFIX = "__rr_state__:";

function toHref(to: To, currentPath: string): string {
    if (typeof to === "string") return resolveRelative(to, currentPath);
    const path = to.pathname ? resolveRelative(to.pathname, currentPath) : currentPath;
    const search = to.search ? (to.search.startsWith("?") ? to.search : `?${to.search}`) : "";
    const hash = to.hash ? (to.hash.startsWith("#") ? to.hash : `#${to.hash}`) : "";
    return `${path}${search}${hash}`;
}

/** يحاكي حلّ المسارات النسبية في React Router (مثل <Navigate to="way" />) */
function resolveRelative(to: string, currentPath: string): string {
    if (/^(https?:|mailto:|tel:|#|\/)/i.test(to) || to.startsWith("?")) {
        return to.startsWith("?") ? `${currentPath}${to}` : to;
    }
    const base = currentPath.endsWith("/") ? currentPath : `${currentPath}/`;
    const segments = (base + to).split("/");
    const out: string[] = [];
    for (const seg of segments) {
        if (seg === "..") out.pop();
        else if (seg !== "." && seg !== "") out.push(seg);
    }
    return `/${out.join("/")}`;
}

function stateKey(href: string) {
    const clean = href.split("#")[0];
    return STATE_PREFIX + clean;
}

function writeState(href: string, state: unknown) {
    try {
        if (state === undefined || state === null) sessionStorage.removeItem(stateKey(href));
        else sessionStorage.setItem(stateKey(href), JSON.stringify(state));
    } catch {
        /* sessionStorage غير متاح — نتجاهل كما يفعل المتصفح في الوضع الخاص */
    }
}

function readState(href: string): any {
    try {
        const raw = sessionStorage.getItem(stateKey(href));
        return raw ? JSON.parse(raw) : null;
    } catch {
        return null;
    }
}

const isExternal = (href: string) => /^(https?:)?\/\//i.test(href) || /^(mailto:|tel:)/i.test(href);

/* ------------------------------------------------------------------ */
/* Hooks                                                                */
/* ------------------------------------------------------------------ */

export function useLocation() {
    const pathname = usePathname() || "/";
    const sp = useNextSearchParams();
    const search = sp && sp.toString() ? `?${sp.toString()}` : "";
    const [hash, setHash] = useState("");
    const [state, setState] = useState<any>(null);

    useEffect(() => {
        setHash(window.location.hash);
        setState(readState(`${pathname}${search}`) ?? readState(pathname));
    }, [pathname, search]);

    return useMemo(
        () => ({ pathname, search, hash, state, key: `${pathname}${search}` }),
        [pathname, search, hash, state]
    );
}

export function useNavigate() {
    const router = useRouter();
    const pathname = usePathname() || "/";

    return useCallback(
        (to: To | number, options?: { replace?: boolean; state?: unknown; preventScrollReset?: boolean }) => {
            if (typeof to === "number") {
                if (to < 0) router.back();
                else router.forward();
                return;
            }
            const href = toHref(to, pathname);
            if (isExternal(href)) {
                window.location.href = href;
                return;
            }
            writeState(href, options?.state);
            const scroll = !options?.preventScrollReset;
            if (options?.replace) router.replace(href, { scroll });
            else router.push(href, { scroll });
        },
        [router, pathname]
    );
}

export function useParams<T extends Record<string, string> = Record<string, string>>(): T {
    const params = useNextParams() || {};
    const pathname = usePathname() || "/";
    // Next قد يعيد string[] لمسارات catch-all؛ React Router يعيد string دائماً
    const flat: Record<string, string> = {};
    for (const [k, v] of Object.entries(params)) {
        flat[k] = Array.isArray(v) ? v.join("/") : decodeURIComponent(String(v));
    }
    // روابط البرامج /training-courses/{id}-{slug}: كل المكوّنات (التفاصيل، الجدول، الدفع، PDF)
    // تستخدم id لطلبات الـ API — نعيد الرقم وحده هنا مرة واحدة بدل تعديل كل مكوّن
    if (flat.id && pathname.startsWith(`${COURSE_BASE}/`)) {
        flat.id = parseCourseParam(flat.id) ?? flat.id;
    }
    return flat as T;
}

type SetSearchParams = (
    next:
        | URLSearchParams
        | Record<string, string | string[]>
        | string
        | ((prev: URLSearchParams) => URLSearchParams | Record<string, string | string[]>),
    opts?: { replace?: boolean }
) => void;

export function useSearchParams(): [URLSearchParams, SetSearchParams] {
    const sp = useNextSearchParams();
    const router = useRouter();
    const pathname = usePathname() || "/";

    const params = useMemo(() => new URLSearchParams(sp ? sp.toString() : ""), [sp]);

    const setParams: SetSearchParams = useCallback(
        (next, opts) => {
            const value = typeof next === "function" ? next(new URLSearchParams(params.toString())) : next;
            let usp: URLSearchParams;
            if (value instanceof URLSearchParams) usp = value;
            else if (typeof value === "string") usp = new URLSearchParams(value);
            else {
                usp = new URLSearchParams();
                for (const [k, v] of Object.entries(value || {})) {
                    if (Array.isArray(v)) v.forEach((item) => usp.append(k, String(item)));
                    else if (v !== undefined && v !== null) usp.set(k, String(v));
                }
            }
            const qs = usp.toString();
            const href = qs ? `${pathname}?${qs}` : pathname;
            if (opts?.replace) router.replace(href, { scroll: false });
            else router.push(href, { scroll: false });
        },
        [params, pathname, router]
    );

    return [params, setParams];
}

/* ------------------------------------------------------------------ */
/* Components                                                           */
/* ------------------------------------------------------------------ */

type LinkProps = Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> & {
    to: To;
    replace?: boolean;
    state?: unknown;
    reloadDocument?: boolean;
    preventScrollReset?: boolean;
    children?: React.ReactNode;
};

export const Link = forwardRef<HTMLAnchorElement, LinkProps>(function Link(
    { to, replace, state, reloadDocument, preventScrollReset, onClick, target, ...rest },
    ref
) {
    const pathname = usePathname() || "/";
    const href = toHref(to, pathname);

    if (reloadDocument || isExternal(href) || (target && target !== "_self")) {
        return <a ref={ref} href={href} target={target} onClick={onClick} {...rest} />;
    }

    return (
        <NextLink
            ref={ref}
            href={href}
            replace={replace}
            scroll={!preventScrollReset}
            target={target}
            onClick={(e) => {
                writeState(href, state);
                onClick?.(e);
            }}
            {...rest}
        />
    );
});

type NavLinkRenderProps = { isActive: boolean; isPending: boolean; isTransitioning: boolean };
type NavLinkProps = Omit<LinkProps, "className" | "style" | "children"> & {
    end?: boolean;
    caseSensitive?: boolean;
    className?: string | ((p: NavLinkRenderProps) => string | undefined);
    style?: React.CSSProperties | ((p: NavLinkRenderProps) => React.CSSProperties | undefined);
    children?: React.ReactNode | ((p: NavLinkRenderProps) => React.ReactNode);
};

export const NavLink = forwardRef<HTMLAnchorElement, NavLinkProps>(function NavLink(
    { to, end, caseSensitive, className, style, children, ...rest },
    ref
) {
    const pathname = usePathname() || "/";
    const target = toHref(to, pathname).split(/[?#]/)[0];
    const a = caseSensitive ? pathname : pathname.toLowerCase();
    const b = caseSensitive ? target : target.toLowerCase();
    const isActive = !isExternal(target) && (end ? a === b : a === b || (b !== "/" && a.startsWith(`${b}/`)));
    const p = { isActive, isPending: false, isTransitioning: false };

    // React Router يضيف الصنف "active" افتراضياً — والـ CSS الأصلي يعتمد عليه (.active)
    const cls =
        typeof className === "function" ? className(p) : [className, isActive ? "active" : ""].filter(Boolean).join(" ");

    return (
        <Link
            ref={ref}
            to={to}
            className={cls || undefined}
            style={typeof style === "function" ? style(p) : style}
            aria-current={isActive ? "page" : undefined}
            {...rest}
        >
            {typeof children === "function" ? children(p) : children}
        </Link>
    );
});

export function Navigate({ to, replace = true, state }: { to: To; replace?: boolean; state?: unknown }) {
    const navigate = useNavigate();
    useEffect(() => {
        navigate(to, { replace, state });
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);
    return null;
}

/* ------------------------------------------------------------------ */
/* Outlet — يعرض children الخاصة بـ layout في Next                      */
/* ------------------------------------------------------------------ */

const OutletContext = createContext<React.ReactNode>(null);

export function OutletProvider({ children, outlet }: { children: React.ReactNode; outlet: React.ReactNode }) {
    return <OutletContext.Provider value={outlet}>{children}</OutletContext.Provider>;
}

export function Outlet() {
    return <>{useContext(OutletContext)}</>;
}

/* لا حاجة لها بعد الترحيل (التوجيه أصبح بنظام الملفات) — تُصدَّر للتوافق فقط */
export const BrowserRouter = ({ children }: { children: React.ReactNode }) => <>{children}</>;
export const Routes = ({ children }: { children?: React.ReactNode }) => <>{children}</>;
export const Route = (_: Record<string, unknown>) => null;
