"use client";

import { useEffect, useState } from "react";
import { MeApi } from "@/lib/api";

/**
 * Which permission pages put each screen in the menu (PRD 1.1, ST-09 "Show in menu"). A screen
 * shows when the user's role has "Show in menu" on any of its pages. Page ids are the API's
 * catalogue (`pharmacy-api/src/permissions/catalog.ts`).
 */
export const SCREEN_PAGES: Record<string, string[]> = {
    "/dashboard": ["Dashboard/Overview"],
    "/pos": ["POS/POS sales"],
    "/shifts": ["POS/Cashier balances"],
    "/shift": ["POS/Open and close shift"],
    "/preorders": ["POS/Preorders"],
    "/credit-notes": ["POS/Credit notes"],
    "/prescriptions": ["Customers/Prescriptions"],
    "/inventory": ["Inventory/Products"],
    "/purchase-orders": ["Inventory/Purchase orders"],
    "/branch-transfers": ["Inventory/Branch transfers"],
    "/stocktakes": ["Inventory/Stocktakes"],
    "/waste": ["Inventory/Waste"],
    "/issues": ["Inventory/Issues"],
    "/labels": ["Inventory/Products"],
    "/price-groups": ["Inventory/Price groups"],
    "/customers": ["Customers/Customer list"],
    "/customer-groups": ["Customers/Customer groups", "Customers/Schemes"],
    "/suppliers": ["Suppliers/Supplier list", "Suppliers/Supplier returns"],
    "/expenses": ["Accounts/Expenses"],
    "/accounts": ["Accounts/General ledger"],
    "/receivables": ["Accounts/Invoices", "Accounts/Quotations", "Accounts/Claims", "Accounts/Receivables"],
    "/payables": ["Accounts/Supplier bills", "Accounts/Payables"],
    "/employees": ["HRM/Employees", "HRM/Leave"],
    "/payroll": ["HRM/Payroll", "HRM/Statutory rates"],
    "/reports": ["Reports/Sales reports", "Reports/Sales history", "Reports/Stock reports"],
    "/users": ["Settings/Users and roles"],
    "/settings": ["Settings/General settings", "Settings/Branches", "Settings/Users and roles"],
    "/promotions": ["Settings/Promotions"],
    "/integrations/mpesa": ["Integrations/M-Pesa"],
};

/** The SCREEN_PAGES entry for a path: the exact route, else the longest one it sits under ("/pos/x" → "/pos"). */
export function screenOf(pathname: string): string | undefined {
    const path = pathname.replace(/\/+$/, "") || "/";
    if (SCREEN_PAGES[path]) return path;
    return Object.keys(SCREEN_PAGES)
        .filter(href => path.startsWith(href + "/"))
        .sort((a, b) => b.length - a.length)[0];
}

type Grants = Record<string, string[]>;

/**
 * The signed-in user's menu permissions. Until they load, or against an API without them, it
 * falls back to the screen's old fixed role list, so menus never flash empty or vanish.
 */
export function useMenuPermissions() {
    const [grants, setGrants] = useState<Grants | null>(null);
    const [superAdmin, setSuperAdmin] = useState(false);
    const [settled, setSettled] = useState(false);

    useEffect(() => {
        let live = true;
        MeApi.permissions()
            .then(p => { if (live) { setGrants(p.grants ?? {}); setSuperAdmin(!!p.superAdmin); } })
            .catch(() => { /* older API or offline: keep the role fallback */ })
            .finally(() => { if (live) setSettled(true); });
        return () => { live = false; };
    }, []);

    /** Show `href` in the menu? `fallbackRoles` is the screen's old fixed list, used until permissions load. */
    const showsInMenu = (href: string, role: string | undefined, fallbackRoles?: string[]) => {
        const pages = SCREEN_PAGES[href];
        if (grants && pages) return superAdmin || pages.some(p => grants[p]?.includes("Show in menu"));
        return !fallbackRoles || fallbackRoles.includes(role || "");
    };

    /** Can the user do `action` on `page`? Unknown (not loaded) counts as no. */
    const can = (page: string, action: string) => superAdmin || !!grants?.[page]?.includes(action);

    /**
     * May the user open `href` (ST-09: a page is seen only with Read on it)? True while permissions load or
     * against an older API, so nothing flashes a refusal; the API still refuses what the role can't read.
     */
    const mayOpen = (href: string) => {
        const pages = SCREEN_PAGES[href];
        if (!grants || !pages) return true;
        return superAdmin || pages.some(p => grants[p]?.includes("Read"));
    };

    /** `settled`: the permissions request has answered either way (an older API leaves `loaded` false). */
    return { loaded: grants !== null, settled, showsInMenu, can, mayOpen };
}
