/**
 * useMandateRoles Hook
 * 
 * Hook for managing roles within a specific mandate.
 * Uses the /api/rbac/roles endpoints.
 */

import { useState, useCallback, useRef } from 'react';
import api from '../api';

// Types
export interface Role {
  id: string;
  roleLabel: string;
  description?: string | { [key: string]: string };
  mandateId?: string;
  featureInstanceId?: string;
  featureCode?: string;
  isSystemRole?: boolean;
  isTemplate?: boolean;
  createdAt?: number;
  updatedAt?: number;
}

export interface RoleCreate {
  roleLabel: string;
  description?: string | { [key: string]: string };
  mandateId?: string;
  featureInstanceId?: string;
  featureCode?: string;
}

export interface RoleUpdate {
  roleLabel?: string;
  description?: string | { [key: string]: string };
  mandateId?: string | null;
}

export interface PaginationParams {
  page?: number;
  pageSize?: number;
  search?: string;
  filters?: Record<string, any>;
  sort?: Array<{ field: string; direction: 'asc' | 'desc' }>;
  scopeFilter?: 'all' | 'mandate' | 'global';  // Backend filter for role scope
}

export interface PaginationMetadata {
  currentPage: number;
  pageSize: number;
  totalItems: number;
  totalPages: number;
}

/**
 * Hook for managing mandate roles
 */
export function useMandateRoles() {
  const [roles, setRoles] = useState<Role[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [pagination, setPagination] = useState<PaginationMetadata | null>(null);
  
  // Store current mandateId for refetch
  const currentMandateIdRef = useRef<string | undefined>(undefined);

  /**
   * Fetch all roles with pagination support
   * @param mandateIdOrParams - Either a mandateId string (backward compatible) or pagination params
   * @param additionalParams - Additional parameters like scopeFilter (when first param is mandateId)
   */
  const fetchRoles = useCallback(async (
    mandateIdOrParams?: string | PaginationParams,
    additionalParams?: PaginationParams
  ): Promise<Role[]> => {
    setLoading(true);
    setError(null);
    
    try {
      const headers: Record<string, string> = {};
      let paginationParams: PaginationParams = {};
      let mandateId: string | undefined;
      let scopeFilter: string | undefined;
      
      // Handle backward compatibility: first param can be mandateId string or pagination object
      if (typeof mandateIdOrParams === 'string') {
        mandateId = mandateIdOrParams;
        currentMandateIdRef.current = mandateId;
        // If additional params provided, use them
        if (additionalParams) {
          paginationParams = additionalParams;
          scopeFilter = additionalParams.scopeFilter;
        }
      } else if (mandateIdOrParams && typeof mandateIdOrParams === 'object') {
        paginationParams = mandateIdOrParams;
        mandateId = currentMandateIdRef.current;
        scopeFilter = mandateIdOrParams.scopeFilter;
      }
      
      if (mandateId) {
        headers['X-Mandate-Id'] = mandateId;
      }
      
      // Build query params for pagination (exclude scopeFilter from pagination JSON)
      const { scopeFilter: _, ...paginationWithoutScope } = paginationParams;
      const queryParams: Record<string, string> = {};
      if (Object.keys(paginationWithoutScope).length > 0) {
        queryParams.pagination = JSON.stringify(paginationWithoutScope);
      }
      // Do NOT include feature template roles - they belong to Feature-Rollen page
      // According to admin_ui_concept.md: Filter: featureCode=null AND featureInstanceId=null
      queryParams.includeTemplates = 'false';
      // Include mandate-specific roles for the selected mandate
      if (mandateId) {
        queryParams.mandateId = mandateId;
      }
      // Include scopeFilter as separate query parameter
      if (scopeFilter) {
        queryParams.scopeFilter = scopeFilter;
      }
      
      const response = await api.get('/api/rbac/roles', { 
        headers,
        params: queryParams
      });
      
      let data: Role[] = [];
      let paginationMeta: PaginationMetadata | null = null;
      
      if (response.data?.items && Array.isArray(response.data.items)) {
        data = response.data.items;
        if (response.data.pagination) {
          paginationMeta = response.data.pagination;
        }
      } else if (Array.isArray(response.data)) {
        data = response.data;
      }
      
      // No client-side filtering needed - backend already filters
      
      setRoles(data);
      setPagination(paginationMeta);
      return data;
    } catch (err: any) {
      const errorMessage = err.response?.data?.detail || err.message || 'Failed to fetch roles';
      setError(errorMessage);
      setRoles([]);
      setPagination(null);
      return [];
    } finally {
      setLoading(false);
    }
  }, []);

  /**
   * Get a single role by ID
   */
  const getRole = useCallback(async (roleId: string): Promise<Role | null> => {
    try {
      const response = await api.get(`/api/rbac/roles/${roleId}`);
      return response.data;
    } catch (err: any) {
      console.error('Error fetching role:', err);
      return null;
    }
  }, []);

  /**
   * Create a new role
   */
  const createRole = useCallback(async (
    data: RoleCreate,
    mandateId?: string
  ): Promise<{ success: boolean; data?: Role; error?: string }> => {
    setLoading(true);
    setError(null);
    try {
      const headers: Record<string, string> = {};
      if (mandateId) {
        headers['X-Mandate-Id'] = mandateId;
      }
      
      const response = await api.post('/api/rbac/roles', data, { headers });
      return { success: true, data: response.data };
    } catch (err: any) {
      const errorMessage = err.response?.data?.detail || err.message || 'Failed to create role';
      setError(errorMessage);
      return { success: false, error: errorMessage };
    } finally {
      setLoading(false);
    }
  }, []);

  /**
   * Update an existing role
   */
  const updateRole = useCallback(async (
    roleId: string,
    data: RoleUpdate
  ): Promise<{ success: boolean; data?: Role; error?: string }> => {
    setLoading(true);
    setError(null);
    try {
      const response = await api.put(`/api/rbac/roles/${roleId}`, data);
      // Optimistically update local state (convert null to undefined for mandateId)
      const updateData = {
        ...data,
        mandateId: data.mandateId === null ? undefined : data.mandateId
      };
      setRoles(prev => prev.map(r => r.id === roleId ? { ...r, ...updateData } : r));
      return { success: true, data: response.data };
    } catch (err: any) {
      const errorMessage = err.response?.data?.detail || err.message || 'Failed to update role';
      setError(errorMessage);
      return { success: false, error: errorMessage };
    } finally {
      setLoading(false);
    }
  }, []);

  /**
   * Delete a role
   */
  const deleteRole = useCallback(async (
    roleId: string
  ): Promise<{ success: boolean; error?: string }> => {
    setLoading(true);
    setError(null);
    try {
      await api.delete(`/api/rbac/roles/${roleId}`);
      // Optimistically update local state
      setRoles(prev => prev.filter(r => r.id !== roleId));
      return { success: true };
    } catch (err: any) {
      const errorMessage = err.response?.data?.detail || err.message || 'Failed to delete role';
      setError(errorMessage);
      return { success: false, error: errorMessage };
    } finally {
      setLoading(false);
    }
  }, []);

  /**
   * Get role options (for dropdowns)
   */
  const fetchRoleOptions = useCallback(async (): Promise<Array<{ value: string; label: string }>> => {
    try {
      const response = await api.get('/api/rbac/roles/options');
      if (Array.isArray(response.data)) {
        return response.data.map((r: any) => ({
          value: r.id || r.value,
          label: r.roleLabel || r.label || r.id
        }));
      }
      return [];
    } catch (err: any) {
      console.error('Error fetching role options:', err);
      return [];
    }
  }, []);

  /**
   * Get users with a specific role
   */
  const getUsersWithRole = useCallback(async (
    roleLabel: string
  ): Promise<Array<{ userId: string; username: string; email?: string }>> => {
    try {
      const response = await api.get(`/api/rbac/roles/roles/${roleLabel}/users`);
      return Array.isArray(response.data) ? response.data : [];
    } catch (err: any) {
      console.error('Error fetching users with role:', err);
      return [];
    }
  }, []);

  /**
   * Filter roles by type
   */
  const getMandateRoles = useCallback((mandateId: string) => {
    return roles.filter(r => 
      r.mandateId === mandateId && !r.featureInstanceId
    );
  }, [roles]);

  const getFeatureRoles = useCallback((featureInstanceId: string) => {
    return roles.filter(r => r.featureInstanceId === featureInstanceId);
  }, [roles]);

  const getGlobalRoles = useCallback(() => {
    return roles.filter(r => !r.mandateId && !r.featureInstanceId);
  }, [roles]);

  const getTemplateRoles = useCallback(() => {
    return roles.filter(r => r.isTemplate === true);
  }, [roles]);

  return {
    roles,
    loading,
    error,
    pagination,
    fetchRoles,
    getRole,
    createRole,
    updateRole,
    deleteRole,
    fetchRoleOptions,
    getUsersWithRole,
    getMandateRoles,
    getFeatureRoles,
    getGlobalRoles,
    getTemplateRoles,
  };
}

export default useMandateRoles;
