import { createContext, useContext, useState, useEffect } from "react";
import api from "../api/client";

const AuthContext = createContext(null);

export function AuthProvider({ children }) {
  const [user, setUser] = useState(() => {
    const stored = localStorage.getItem("user");
    return stored ? JSON.parse(stored) : null;
  });
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const token = localStorage.getItem("access_token");
    if (!token) {
      setUser(null);
      setLoading(false);
      return;
    }

    try {
      const payload = JSON.parse(atob(token.split(".")[1]));
      if (payload.exp * 1000 < Date.now()) {
        localStorage.removeItem("access_token");
        localStorage.removeItem("user");
        setUser(null);
      }
    } catch {
      localStorage.removeItem("access_token");
      localStorage.removeItem("user");
      setUser(null);
    }
    setLoading(false);
  }, []);

  const login = async (email, password) => {
    const data = await api.post("/auth/login", { email, password });
    localStorage.setItem("access_token", data.access_token);
    const userInfo = {
      name: data.name,
      role: data.role,
      permissions: data.permissions || null,
    };
    localStorage.setItem("user", JSON.stringify(userInfo));
    setUser(userInfo);

    // Fetch full profile from /staff/me for up-to-date permissions
    try {
      const me = await api.get("/staff/me");
      if (me.permissions) {
        const updated = { ...userInfo, permissions: me.permissions };
        localStorage.setItem("user", JSON.stringify(updated));
        setUser(updated);
      }
    } catch {
      // Non-critical, permissions from login response are used
    }

    return data;
  };

  const logout = () => {
    localStorage.removeItem("access_token");
    localStorage.removeItem("user");
    setUser(null);
  };

  const hasRole = (...roles) => {
    if (!user) return false;
    if (user.role === "sysadmin") return true;
    return roles.includes(user.role);
  };

  /**
   * hasPermission(section, action)
   *
   * Sections and their action keys:
   *   melodies:      view, add, delete, safe_edit, full_edit, archetype_access, settings_access, compose_access
   *   devices:       view, add, delete, safe_edit, edit_bells, edit_clock, edit_warranty, full_edit, control
   *   app_users:     view, add, delete, safe_edit, full_edit
   *   issues_notes:  view, add, delete, edit
   *   mail:          view, compose, reply
   *   crm:           activity_log
   *   crm_customers: full_access, overview, orders_view, orders_edit, quotations_view, quotations_edit,
   *                  comms_view, comms_log, comms_edit, comms_compose, add, delete,
   *                  files_view, files_edit, devices_view, devices_edit
   *   crm_orders:    view (→ crm_customers.orders_view), edit (→ crm_customers.orders_edit)  [derived]
   *   crm_products:  view, add, edit
   *   mfg:           view_inventory, edit, provision, firmware_view, firmware_edit
   *   api_reference: access
   *   mqtt:          access
   */
  const hasPermission = (section, action) => {
    if (!user) return false;
    // sysadmin and admin have full access
    if (user.role === "sysadmin" || user.role === "admin") return true;

    const perms = user.permissions;
    if (!perms) return false;

    // crm_orders is derived from crm_customers
    if (section === "crm_orders") {
      const cc = perms.crm_customers;
      if (!cc) return false;
      if (cc.full_access) return true;
      if (action === "view") return !!cc.orders_view;
      if (action === "edit") return !!cc.orders_edit;
      return false;
    }

    const sectionPerms = perms[section];
    if (!sectionPerms) return false;

    // crm_customers.full_access grants everything in that section
    if (section === "crm_customers" && sectionPerms.full_access) return true;

    return !!sectionPerms[action];
  };

  return (
    <AuthContext.Provider value={{ user, login, logout, loading, hasRole, hasPermission }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}
