import { create } from 'zustand';
import api from './api';

// Phase 1 PR 1: store for auxiliary role grants + class covers.

export interface UserRole {
  id: number;
  uid: string;
  user_id: number;
  role: string;
  scope_class_id: number | null;
  scope_subject_id: number | null;
  scope_cohort_id: number | null;
  starts_at: string | null;
  expires_at: string | null;
  reason: string | null;
  granted_by: number | null;
  granted_at: string;
  revoked_by: number | null;
  revoked_at: string | null;
  revoke_reason: string | null;
  scope_class_name?: string;
  scope_subject_name?: string;
}

export interface ActiveCover {
  id: number;
  user_id: number;
  role: string;
  scope_class_id: number;
  scope_subject_id: number | null;
  starts_at: string | null;
  expires_at: string | null;
  reason: string | null;
  granted_by: number | null;
  granted_at: string;
  first_name: string;
  last_name: string;
  email: string;
}

interface UserRolesState {
  grantsByUser: Record<number, UserRole[]>;
  loading: boolean;
  error: string | null;
  fetchUserRoles: (userId: number) => Promise<UserRole[]>;
  grantRole: (
    userId: number,
    payload: {
      role: string;
      scope_class_id?: number | null;
      scope_subject_id?: number | null;
      scope_cohort_id?: number | null;
      starts_at?: string | null;
      expires_at?: string | null;
      reason?: string | null;
    }
  ) => Promise<UserRole>;
  updateGrant: (id: number, payload: { expires_at?: string | null; reason?: string | null }) => Promise<UserRole>;
  revokeGrant: (id: number, revoke_reason?: string) => Promise<void>;
  fetchActiveCovers: (classId: number, date?: string) => Promise<ActiveCover[]>;
}

export const useUserRolesStore = create<UserRolesState>((set, get) => ({
  grantsByUser: {},
  loading: false,
  error: null,

  fetchUserRoles: async (userId) => {
    set({ loading: true, error: null });
    try {
      const { data } = await api.get(`/users/${userId}/roles`);
      const grants = data.grants || [];
      set((s) => ({ grantsByUser: { ...s.grantsByUser, [userId]: grants }, loading: false }));
      return grants;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to load user roles';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  grantRole: async (userId, payload) => {
    set({ loading: true, error: null });
    try {
      const { data } = await api.post(`/users/${userId}/roles`, payload);
      // Refresh the list for that user so callers see the new row.
      await get().fetchUserRoles(userId);
      return data;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to grant role';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  updateGrant: async (id, payload) => {
    set({ loading: true, error: null });
    try {
      const { data } = await api.put(`/user-roles/${id}`, payload);
      return data;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to update grant';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  revokeGrant: async (id, revoke_reason) => {
    set({ loading: true, error: null });
    try {
      await api.delete(`/user-roles/${id}`, { data: { revoke_reason } });
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to revoke grant';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  fetchActiveCovers: async (classId, date) => {
    try {
      const { data } = await api.get(`/user-roles/active-covers`, {
        params: { class_id: classId, date },
      });
      return data.covers || [];
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to load active covers';
      set({ error: msg });
      throw new Error(msg);
    }
  },
}));

export const SUPPORTED_AUX_ROLES = [
  'systems_admin', 'school_admin', 'teacher', 'student', 'parent', 'accountant',
  'librarian', 'nurse', 'clubs_head', 'principal', 'hr', 'bursar', 'dining_staff',
  'driver', 'groundsman', 'matron', 'boarding_master', 'security', 'janitor',
] as const;
