// API service for handling HTTP requests
const API_BASE_URL = (() => {
  const dev = typeof import.meta !== 'undefined' && (import.meta as any).env && (import.meta as any).env.DEV;
  if (dev) return '/api';
  const envUrl = typeof import.meta !== 'undefined' && (import.meta as any).env && (import.meta as any).env.VITE_API_BASE_URL ? (import.meta as any).env.VITE_API_BASE_URL as string : '';
  const origin = typeof window !== 'undefined' && window.location && window.location.origin ? window.location.origin : '';
  const base = envUrl || origin || '';
  if (!base) return '/api';
  return base.endsWith('/api') ? base : `${base}/api`;
})();


// API Response types
export interface ApiResponse<T> {
  status: 'success' | 'error';
  message: string;
  data?: T;
  error?: string;
}

// Import types from the types file
import { 
  ContactListResponse, 
  ContactResponse, 
  ContactChildrenResponse, 
  ContactSearchResponse, 
  ContactStatistics, 
  ContactCreateRequest, 
  ContactUpdateRequest, 
  BulkDeleteResponse,
  DepartmentsListResponse,
  Department
} from '../types';
// Note: AuthUser is now defined locally in this file to match API response structure

// Dashboard types
export interface DashboardStats {
  totalContacts: {
    total_contacts: number;
    active_contacts: number;
    inactive_contacts: number;
    new_contacts_30d: number;
    new_contacts_7d: number;
  };
  activeConversations: {
    total_conversations: number;
    active_24h: number;
    active_7d: number;
    direct_conversations: number;
    group_conversations: number;
  };
  onlineContacts: {
    online_now: number;
    busy_now: number;
    offline_now: number;
    recently_active: number;
    active_1h: number;
    active_24h: number;
  };
  securityAlerts: {
    failed_logins_24h: number;
    failed_logins_7d: number;
    password_changes_7d: number;
    deletions_7d: number;
    admin_actions_7d: number;
    total_activities_1h: number;
    total_activities_24h: number;
  };
  recentActivity: Array<{
    action: string;
    target_type: string;
    target_name: string;
    details: string;
    created_at: string;
    user_name: string;
    user_rank: string;
  }>;
  conversationStats: {
    total_messages_24h: number;
    unique_senders_24h: number;
    active_conversations_24h: number;
    text_messages_24h: number;
    system_messages_24h: number;
  };
  userStats: {
    super_admins: number;
    admins: number;
    regular_users: number;
    army_users: number;
    navy_users: number;
    air_force_users: number;
    new_users_30d: number;
    active_users_7d: number;
  };
  users?: {
    admin_users: number;
    view_users: number;
  };
  timestamp: string;
}

// Analytics types
export interface AnalyticsData {
  userActivityChart: Array<{
    date: string;
    new_users: number;
    online_users: number;
  }>;
  conversationChart: Array<{
    date: string;
    new_conversations: number;
    direct_conversations: number;
    group_conversations: number;
  }>;
  messageChart: Array<{
    date: string;
    total_messages: number;
    text_messages: number;
    system_messages: number;
    unique_senders: number;
  }>;
  securityChart: Array<{
    date: string;
    total_activities: number;
    login_activities: number;
    password_activities: number;
    delete_activities: number;
  }>;
  period: string;
  timestamp: string;
}

// Authentication types
export interface LoginRequest {
  login_id: string;
  password: string;
}

export interface LoginResponse {
  user: {
    id: number;
    name: string;
    rank_id: number;
    service_no: string;
    unit_id: number;
    department_id: number;
    role_id: number;
    role: string;
    designation_id: number;
    parent_id: number | null;
    phone: string;
    mobile: string;
    alternative_mobile: string | null;
    email: string;
    avatar: string | null;
    status: string;
    last_seen: string;
    is_active: number;
    created_at: string;
    updated_at: string;
    permissions: string[];
  };
  token: string;
  refreshToken: string;
}

export interface ProfileResponse {
  user: {
    id: number;
    name: string;
    rank_id: number;
    service_no: string;
    unit_id: number;
    department_id: number;
    role_id: number;
    role: string;
    designation_id: number;
    parent_id: number | null;
    phone: string;
    mobile: string;
    alternative_mobile: string | null;
    email: string;
    avatar: string | null;
    status: string;
    last_seen: string;
    is_active: number;
    created_at: string;
    updated_at: string;
    permissions: string[];
  };
}

// Retry function with exponential backoff
async function retryWithBackoff<T>(
  fn: () => Promise<T>,
  maxRetries: number = 3,
  baseDelay: number = 1000
): Promise<T> {
  let lastError: Error | undefined;
  
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error as Error;
      
      // Only retry on 429 (rate limit) errors
      if (attempt < maxRetries && lastError.message.includes('Too many requests')) {
        const delay = baseDelay * Math.pow(2, attempt);
        console.log(`Rate limited, retrying in ${delay}ms... (attempt ${attempt + 1}/${maxRetries + 1})`);
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      
      // Don't retry on other errors or if max retries reached
      throw lastError;
    }
  }
  
  // This should never be reached, but TypeScript needs it
  throw lastError || new Error('Unknown error occurred');
}

// Generic API request function
async function apiRequest<T>(
  endpoint: string,
  options: RequestInit = {}
): Promise<ApiResponse<T>> {
  const url = `${API_BASE_URL}${endpoint}`;
  
  const defaultHeaders: Record<string, string> = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Cache-Control': 'no-cache',
    'Pragma': 'no-cache',
  };

  // Add authorization header if token exists
  const token = localStorage.getItem('authToken');
  console.log('🔍 API Request - Token check:', {
    hasToken: !!token,
    tokenLength: token?.length || 0,
    endpoint: endpoint,
    tokenPreview: token ? token.substring(0, 20) + '...' : 'No token'
  });
  
  if (token) {
    defaultHeaders['Authorization'] = `Bearer ${token}`;
  } else {
    console.warn('⚠️ No authentication token found for API request:', endpoint);
  }

  const config: RequestInit = {
    ...options,
    headers: {
      ...defaultHeaders,
      ...options.headers,
    },
    mode: 'cors',
    credentials: 'omit', // Don't send cookies with CORS
  };

  try {
    // Wrap the fetch call with retry logic for rate limiting
    const response = await retryWithBackoff(async () => {
      // Add timeout to prevent hanging requests
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout

      const response = await fetch(url, {
        ...config,
        signal: controller.signal,
      });

      clearTimeout(timeoutId);
      return response;
    });

    console.log('🔍 API Response:', {
      url: url,
      status: response.status,
      statusText: response.statusText,
      ok: response.ok,
      headers: Object.fromEntries(response.headers.entries())
    });

    // Check if response is ok before trying to parse JSON
    if (!response.ok) {
      let errorMessage = `HTTP error! status: ${response.status}`;
      
      // Handle specific HTTP status codes
      if (response.status === 429) {
        errorMessage = 'Too many requests. Please wait a moment and try again.';
      } else if (response.status === 401) {
        errorMessage = 'Authentication required. Please log in again.';
      } else if (response.status === 403) {
        errorMessage = 'Access denied. You do not have permission to access this resource.';
      } else if (response.status === 404) {
        errorMessage = 'Resource not found.';
      } else if (response.status >= 500) {
        errorMessage = 'Server error. Please try again later.';
      }
      
      try {
        const errorData = await response.json();
        errorMessage = errorData.message || errorMessage;
      } catch {
        // If we can't parse the error response, use the status text
        errorMessage = response.statusText || errorMessage;
      }
      throw new Error(errorMessage);
    }

    // Check if response has content before parsing
    const contentType = response.headers.get('content-type');
    if (!contentType || !contentType.includes('application/json')) {
      throw new Error('Response is not JSON');
    }

    const data = await response.json();
    console.log('🔍 API Success Data:', data);
    return data;
  } catch (error) {
    console.error('API request failed:', error);
    
    // Handle specific error types
    if (error instanceof Error) {
      if (error.name === 'AbortError') {
        throw new Error('Request timeout. Please check your connection and try again.');
      }
      if (error.message.includes('Failed to fetch')) {
        throw new Error('Unable to connect to the server. Please make sure the backend server is running on port 3001.');
      }
      if (error.message.includes('CORS')) {
        throw new Error('CORS error. Please check server configuration.');
      }
      if (error.message.includes('Network error')) {
        throw new Error('Network error. Please check if the backend server is running and try again.');
      }
    }
    
    throw error;
  }
}

// Authentication API functions
export const authApi = {
  // Login user
  async login(credentials: LoginRequest): Promise<ApiResponse<LoginResponse>> {
    return apiRequest<LoginResponse>('/auth/login', {
      method: 'POST',
      body: JSON.stringify(credentials),
    });
  },

  // Logout user (if backend supports it)
  async logout(): Promise<ApiResponse<null>> {
    return apiRequest<null>('/auth/logout', {
      method: 'POST',
    });
  },

  // Refresh token
  async refreshToken(): Promise<ApiResponse<{ token: string; refreshToken: string }>> {
    const refreshToken = localStorage.getItem('refreshToken');
    if (!refreshToken) {
      throw new Error('No refresh token available');
    }

    return apiRequest<{ token: string; refreshToken: string }>('/auth/refresh', {
      method: 'POST',
      body: JSON.stringify({ refreshToken }),
    });
  },

  // Get current user profile
  async getProfile(): Promise<ApiResponse<ProfileResponse>> {
    return apiRequest<ProfileResponse>('/auth/profile');
  },

  // Update user profile
  async updateProfile(profileData: {
    name: string;
    email: string;
    service_no: string;
    mobile: string;
    rank_id: number;
    unit_id: number;
    department_id: number;
    designation_id: number;
  }): Promise<ApiResponse<ProfileResponse>> {
    return apiRequest<ProfileResponse>('/auth/profile', {
      method: 'PUT',
      body: JSON.stringify(profileData),
    });
  },

  // Change user password
  async changePassword(currentPassword: string, newPassword: string): Promise<ApiResponse<null>> {
    return apiRequest<null>('/auth/change-password', {
      method: 'PUT',
      body: JSON.stringify({ currentPassword, newPassword }),
    });
  },
};

// Dashboard API functions
export const dashboardApi = {
  // Get dashboard statistics
  async getStats(): Promise<ApiResponse<DashboardStats>> {
    try {
      const response = await apiRequest<DashboardStats>('/dashboard/stats');
      
      // The API returns { status: "success", data: { ... } }
      // The data property contains the actual dashboard stats
      if (response.status === 'success' && response.data) {
        return {
          status: 'success',
          message: 'Dashboard stats fetched successfully',
          data: response.data
        };
      }
      
      return {
        status: 'error',
        message: response.message || 'Failed to fetch dashboard stats'
      };
    } catch (error) {
      console.error('Dashboard API error:', error);
      throw error;
    }
  },

  // Get dashboard analytics
  async getAnalytics(): Promise<ApiResponse<AnalyticsData>> {
    try {
      const response = await apiRequest<AnalyticsData>('/dashboard/analytics');
      
      // The API returns { status: "success", data: { ... } }
      // The data property contains the actual analytics data
      if (response.status === 'success' && response.data) {
        return {
          status: 'success',
          message: 'Dashboard analytics fetched successfully',
          data: response.data
        };
      }
      
      return {
        status: 'error',
        message: response.message || 'Failed to fetch dashboard analytics'
      };
    } catch (error) {
      console.error('Dashboard Analytics API error:', error);
      throw error;
    }
  },
};

// Token management utilities
export const tokenManager = {
  setTokens(token: string, refreshToken: string): void {
    console.log('🔍 TokenManager - Setting tokens:', {
      tokenLength: token?.length || 0,
      refreshTokenLength: refreshToken?.length || 0,
      tokenPreview: token ? token.substring(0, 20) + '...' : 'No token',
      refreshTokenPreview: refreshToken ? refreshToken.substring(0, 20) + '...' : 'No refresh token'
    });
    
    localStorage.setItem('authToken', token);
    localStorage.setItem('refreshToken', refreshToken);
    
    // Verify storage
    const storedToken = localStorage.getItem('authToken');
    const storedRefreshToken = localStorage.getItem('refreshToken');
    console.log('🔍 TokenManager - Storage verification:', {
      storedTokenExists: !!storedToken,
      storedRefreshTokenExists: !!storedRefreshToken,
      storedTokenLength: storedToken?.length || 0,
      storedRefreshTokenLength: storedRefreshToken?.length || 0
    });
  },

  getToken(): string | null {
    const token = localStorage.getItem('authToken');
    console.log('🔍 TokenManager - Getting token:', {
      hasToken: !!token,
      tokenLength: token?.length || 0,
      tokenPreview: token ? token.substring(0, 20) + '...' : 'No token'
    });
    return token;
  },

  getRefreshToken(): string | null {
    const refreshToken = localStorage.getItem('refreshToken');
    console.log('🔍 TokenManager - Getting refresh token:', {
      hasRefreshToken: !!refreshToken,
      refreshTokenLength: refreshToken?.length || 0,
      refreshTokenPreview: refreshToken ? refreshToken.substring(0, 20) + '...' : 'No refresh token'
    });
    return refreshToken;
  },

  clearTokens(): void {
    console.log('🔍 TokenManager - Clearing tokens');
    localStorage.removeItem('authToken');
    localStorage.removeItem('refreshToken');
  },

  isTokenExpired(token: string): boolean {
    try {
      const payload = JSON.parse(atob(token.split('.')[1]));
      const currentTime = Date.now() / 1000;
      const isExpired = payload.exp < currentTime;
      console.log('🔍 TokenManager - Token expiration check:', {
        currentTime,
        tokenExpiry: payload.exp,
        isExpired,
        timeUntilExpiry: payload.exp - currentTime
      });
      return isExpired;
    } catch (error) {
      console.error('🔍 TokenManager - Error checking token expiration:', error);
      return true;
    }
  },
};

// Service number generation utility
export const generateServiceNumber = async (): Promise<string> => {
  try {
    // Get the latest service number from the API
    const response = await apiRequest<{ latest_service_no: string }>('/contacts/latest-service-no');
    
    if (response.status === 'success' && response.data?.latest_service_no) {
      const latestServiceNo = response.data.latest_service_no;
      
      // Extract the numeric part and increment by 1 for BN format
      const match = latestServiceNo.match(/BN(\d+)$/);
      if (match) {
        const numericPart = parseInt(match[1]);
        const nextNumber = numericPart + 1;
        return `BN${nextNumber.toString().padStart(5, '0')}`;
      }
      
      // Fallback: if format doesn't match BN, try generic numeric extraction
      const genericMatch = latestServiceNo.match(/(\d+)$/);
      if (genericMatch) {
        const numericPart = parseInt(genericMatch[1]);
        const nextNumber = numericPart + 1;
        return `BN${nextNumber.toString().padStart(5, '0')}`;
      }
    }
    
    // Fallback: if no service number exists, start with BN10001
    return 'BN10001';
  } catch {
    console.warn('Service number API not available, using fallback generation');
    // Fallback: generate a timestamp-based service number
    const timestamp = Date.now().toString();
    const randomSuffix = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
    return `BN${timestamp.slice(-5)}${randomSuffix}`;
  }
};

// Contact API functions
export const contactApi = {
  // Get all contacts with optional filtering and tree structure
  async getContacts(params: {
    page?: number;
    limit?: number;
    search?: string;
    contact_type?: 'internal' | 'external';
    parent_id?: number;
    unit_id?: number;
    branch_id?: number;
    tree?: boolean;
    include_inactive?: boolean;
    role_filter?: string;
  } = {}): Promise<ApiResponse<ContactListResponse>> {
    const queryParams = new URLSearchParams();
    
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.limit) queryParams.append('limit', params.limit.toString());
    if (params.search) queryParams.append('search', params.search);
    if (params.contact_type) queryParams.append('contact_type', params.contact_type);
    if (params.parent_id) queryParams.append('parent_id', params.parent_id.toString());
    if (params.unit_id) queryParams.append('unit_id', params.unit_id.toString());
    if (params.branch_id) queryParams.append('branch_id', params.branch_id.toString());
    if (params.tree !== undefined) queryParams.append('tree', params.tree.toString());
    if (params.include_inactive !== undefined) queryParams.append('include_inactive', params.include_inactive.toString());
    if (params.role_filter) queryParams.append('role_filter', params.role_filter);

    const endpoint = `/contacts${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<ContactListResponse>(endpoint);
  },

  // Get contact by ID
  async getContact(id: number, includeChildren: boolean = false): Promise<ApiResponse<ContactResponse>> {
    const queryParams = includeChildren ? '?include_children=true' : '';
    return apiRequest<ContactResponse>(`/contacts/${id}${queryParams}`);
  },

  // Create new contact
  async createContact(contactData: ContactCreateRequest): Promise<ApiResponse<ContactResponse>> {
    return apiRequest<ContactResponse>('/contacts', {
      method: 'POST',
      body: JSON.stringify(contactData),
    });
  },

  // Update contact
  async updateContact(id: number, contactData: ContactUpdateRequest): Promise<ApiResponse<ContactResponse>> {
    return apiRequest<ContactResponse>(`/contacts/${id}`, {
      method: 'PUT',
      body: JSON.stringify(contactData),
    });
  },

  // Delete contact
  async deleteContact(
    id: number,
    options?: { source?: 'management' | 'directory'; scope?: 'department' | 'all'; department_id?: number }
  ): Promise<ApiResponse<null>> {
    const queryParams = new URLSearchParams();
    if (options?.source) queryParams.append('source', options.source);
    if (options?.scope) queryParams.append('scope', options.scope);
    if (typeof options?.department_id === 'number') {
      queryParams.append('department_id', String(options.department_id));
    }
    const endpoint = `/contacts/${id}${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<null>(endpoint, {
      method: 'DELETE',
    });
  },

  // Change contact password
  async changePassword(id: number, newPassword: string): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/contacts/${id}/change-password`, {
      method: 'PUT',
      body: JSON.stringify({ password: newPassword }),
    });
  },

  // Get contact children
  async getContactChildren(id: number): Promise<ApiResponse<ContactChildrenResponse>> {
    return apiRequest<ContactChildrenResponse>(`/contacts/${id}/children`);
  },

  // Search contacts
  async searchContacts(params: {
    q: string;
    contact_type?: 'internal' | 'external';
    limit?: number;
  }): Promise<ApiResponse<ContactSearchResponse>> {
    const queryParams = new URLSearchParams();
    queryParams.append('q', params.q);
    if (params.contact_type) queryParams.append('contact_type', params.contact_type);
    if (params.limit) queryParams.append('limit', params.limit.toString());

    return apiRequest<ContactSearchResponse>(`/contacts/search?${queryParams.toString()}`);
  },

  // Get contact statistics
  async getContactStatistics(): Promise<ApiResponse<{ statistics: ContactStatistics }>> {
    return apiRequest<{ statistics: ContactStatistics }>('/contacts/statistics');
  },

  // Bulk delete contacts
  async bulkDeleteContacts(contactIds: number[]): Promise<ApiResponse<BulkDeleteResponse>> {
    return apiRequest<BulkDeleteResponse>('/contacts/bulk-delete', {
      method: 'POST',
      body: JSON.stringify({ contactIds }),
    });
  },

  // Move contact to different parent
  async moveContact(id: number, parentId: number): Promise<ApiResponse<ContactResponse>> {
    return apiRequest<ContactResponse>(`/contacts/${id}/move`, {
      method: 'PUT',
      body: JSON.stringify({ parent_id: parentId }),
    });
  },
};

// Organizational API Types
export interface Unit {
  id: number;
  name: string;
  order_id: number;
  code: string;
  description: string;
  parent_id: number | null;
  parent_name: string | null;
  is_active: number;
  created_by: number;
  creator_name: string | null;
  created_at: string;
  updated_at: string;
  total_users: number;
  total_departments: number;
  children: Unit[];
}

export interface UnitStatistics {
  total_units: number;
  root_units: string;
  child_units: string;
  total_users: number;
  total_departments: number;
}

export interface UnitPagination {
  page: number;
  limit: number;
  total: number;
}

export interface UnitFilters {
  search: string;
  parent_id: number | null;
  tree: boolean;
  include_inactive: boolean;
}

export interface UnitsListResponse {
  units: Unit[];
  statistics: UnitStatistics;
  pagination: UnitPagination;
  filters: UnitFilters;
}

export interface Branch {
  id: number;
  name: string;
  code: string;
  description: string;
  unit_id: number;
  unit_name: string;
  parent_id: number | null;
  parent_name: string | null;
  is_active: number;
  created_by: number;
  created_by_name: string | null;
  created_at: string;
  updated_at: string;
  children: Branch[];
}

export interface SubBranch {
  id: number;
  name: string;
  code: string;
  description: string;
  branch_id: number;
  branch_name: string;
  parent_id: number | null;
  parent_name: string | null;
  is_active: number;
  created_by: number;
  created_by_name: string | null;
  created_at: string;
  updated_at: string;
  children: SubBranch[];
}

export interface CreateUnitRequest {
  name: string;
  code: string;
  description?: string;
  parent_id?: number;
}

export interface CreateBranchRequest {
  name: string;
  code: string;
  description?: string;
  unit_id: number;
  parent_id?: number;
}

export interface CreateSubBranchRequest {
  name: string;
  code: string;
  description?: string;
  branch_id: number;
  parent_id?: number;
}

// Organizational API functions
export const organizationalApi = {
  // Unit Management
  async getUnits(params: {
    search?: string;
    parent_id?: number | null;
    is_active?: boolean;
    page?: number;
    limit?: number;
    tree?: boolean;
    include_inactive?: boolean;
  } = {}): Promise<ApiResponse<UnitsListResponse>> {
    const queryParams = new URLSearchParams();
    if (params.search) queryParams.append('search', params.search);
    if (params.parent_id !== undefined) queryParams.append('parent_id', params.parent_id?.toString() || 'null');
    if (params.is_active !== undefined) queryParams.append('is_active', params.is_active.toString());
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.limit) queryParams.append('limit', params.limit.toString());
    if (params.tree !== undefined) queryParams.append('tree', params.tree.toString());
    if (params.include_inactive !== undefined) queryParams.append('include_inactive', params.include_inactive.toString());
    
    // Add cache-busting parameter to force fresh data
    queryParams.append('_t', Date.now().toString());

    const endpoint = `/units${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<UnitsListResponse>(endpoint);
  },

  async getUnitTree(): Promise<ApiResponse<Unit[]>> {
    return apiRequest<Unit[]>('/units/tree');
  },

  async createUnit(unitData: CreateUnitRequest): Promise<ApiResponse<Unit>> {
    return apiRequest<Unit>('/units', {
      method: 'POST',
      body: JSON.stringify(unitData),
    });
  },

  async updateUnit(id: number, unitData: Partial<CreateUnitRequest>): Promise<ApiResponse<Unit>> {
    return apiRequest<Unit>(`/units/${id}`, {
      method: 'PUT',
      body: JSON.stringify(unitData),
    });
  },

  async deleteUnit(id: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/units/${id}`, {
      method: 'DELETE',
    });
  },

  // Branch Management
  async getBranches(params: {
    search?: string;
    unit_id?: number;
    parent_id?: number | null;
    is_active?: boolean;
  } = {}): Promise<ApiResponse<Branch[]>> {
    const queryParams = new URLSearchParams();
    if (params.search) queryParams.append('search', params.search);
    if (params.unit_id) queryParams.append('unit_id', params.unit_id.toString());
    if (params.parent_id !== undefined) queryParams.append('parent_id', params.parent_id?.toString() || 'null');
    if (params.is_active !== undefined) queryParams.append('is_active', params.is_active.toString());

    const endpoint = `/branches${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<Branch[]>(endpoint);
  },

  async getBranchTree(): Promise<ApiResponse<Branch[]>> {
    return apiRequest<Branch[]>('/branches/tree');
  },

  async createBranch(branchData: CreateBranchRequest): Promise<ApiResponse<Branch>> {
    return apiRequest<Branch>('/branches', {
      method: 'POST',
      body: JSON.stringify(branchData),
    });
  },

  // Sub-Branch Management
  async getSubBranches(params: {
    search?: string;
    branch_id?: number;
    parent_id?: number | null;
    is_active?: boolean;
  } = {}): Promise<ApiResponse<SubBranch[]>> {
    const queryParams = new URLSearchParams();
    if (params.search) queryParams.append('search', params.search);
    if (params.branch_id) queryParams.append('branch_id', params.branch_id.toString());
    if (params.parent_id !== undefined) queryParams.append('parent_id', params.parent_id?.toString() || 'null');
    if (params.is_active !== undefined) queryParams.append('is_active', params.is_active.toString());

    const endpoint = `/sub-branches${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<SubBranch[]>(endpoint);
  },

  async getSubBranchTree(): Promise<ApiResponse<SubBranch[]>> {
    return apiRequest<SubBranch[]>('/sub-branches/tree');
  },

  async createSubBranch(subBranchData: CreateSubBranchRequest): Promise<ApiResponse<SubBranch>> {
    return apiRequest<SubBranch>('/sub-branches', {
      method: 'POST',
      body: JSON.stringify(subBranchData),
    });
  },
};

// Designation API Types
export interface Designation {
  id: number;
  name: string;
  department_id: number | null;
  department_name: string | null;
  parent_id: number | null;
  parent_name: string | null;
  description?: string;
  is_active: number;
  created_at: string;
  updated_at: string;
  children: Designation[];
}

// Rank API Types
export interface Rank {
  id: number;
  name: string;
  level: number;
  description?: string;
  is_active: number;
  created_at: string;
  updated_at: string;
}

// Designations API functions
export const designationsApi = {
  // Get all designations
  async getDesignations(params?: {
    department_id?: number;
    parent_id?: number | null;
    search?: string;
    page?: number;
    limit?: number;
    include_inactive?: boolean;
  }): Promise<ApiResponse<{ designations: Designation[]; pagination?: any }>> {
    const queryParams = new URLSearchParams();
    if (params?.department_id) queryParams.append('department_id', params.department_id.toString());
    if (params?.parent_id !== undefined) queryParams.append('parent_id', params.parent_id?.toString() || 'null');
    if (params?.search) queryParams.append('search', params.search);
    if (params?.page) queryParams.append('page', params.page.toString());
    if (params?.limit) queryParams.append('limit', params.limit.toString());
    if (params?.include_inactive !== undefined) queryParams.append('include_inactive', params.include_inactive.toString());
    
    const queryString = queryParams.toString();
    return apiRequest<{ designations: Designation[]; pagination?: any }>(`/designations${queryString ? `?${queryString}` : ''}`);
  },

  // Get single designation
  async getDesignation(id: number): Promise<ApiResponse<{ designation: Designation }>> {
    return apiRequest<{ designation: Designation }>(`/designations/${id}`);
  },

  // Create new designation
  async createDesignation(data: {
    name: string;
    department_id?: number;
    parent_id?: number | null;
    description?: string;
  }): Promise<ApiResponse<{ designation: Designation }>> {
    return apiRequest<{ designation: Designation }>('/designations', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  },

  // Update designation
  async updateDesignation(id: number, data: {
    name: string;
    department_id?: number;
    parent_id?: number | null;
    description?: string;
  }): Promise<ApiResponse<{ designation: Designation }>> {
    return apiRequest<{ designation: Designation }>(`/designations/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  },

  // Delete designation
  async deleteDesignation(id: number): Promise<ApiResponse<void>> {
    return apiRequest<void>(`/designations/${id}`, {
      method: 'DELETE',
    });
  },

  // Get designations for dropdown (simplified version)
  async getDesignationsForDropdown(departmentId?: number): Promise<ApiResponse<Designation[]>> {
    try {
      const response = await this.getDesignations({ department_id: departmentId });
      
      if (response.status === 'success' && response.data) {
        return {
          status: 'success',
          message: 'Designations fetched successfully',
          data: response.data.designations
        };
      }
      
      return {
        status: 'error',
        message: response.message || 'Failed to fetch designations'
      };
    } catch (error) {
      console.error('Designations API error:', error);
      throw error;
    }
  },

  // Get designations by department ID
  async getDesignationsByDepartment(departmentId: number): Promise<ApiResponse<Designation[]>> {
    try {
      const response = await this.getDesignations({ department_id: departmentId });
      if (response.status === 'success' && response.data) {
        return {
          status: 'success',
          message: 'Designations fetched successfully',
          data: response.data.designations
        };
      }
      return {
        status: 'error',
        message: response.message || 'Failed to fetch designations by department'
      };
    } catch (error) {
      console.error('Error fetching designations by department:', error);
      return {
        status: 'error',
        message: error instanceof Error ? error.message : 'Failed to fetch designations by department'
      };
    }
  },
};

// Ranks API functions
export const ranksApi = {
  // Get all ranks
  async getRanks(): Promise<ApiResponse<Rank[]>> {
    return apiRequest<Rank[]>('/ranks');
  },

  // Get ranks for dropdown (simplified version)
  async getRanksForDropdown(): Promise<ApiResponse<Rank[]>> {
    try {
      const response = await this.getRanks();
      
      if (response.status === 'success' && response.data) {
        return {
          status: 'success',
          message: 'Ranks fetched successfully',
          data: response.data
        };
      }
      
      return {
        status: 'error',
        message: response.message || 'Failed to fetch ranks'
      };
    } catch (error) {
      console.error('Ranks API error:', error);
      throw error;
    }
  },
};

// Departments API functions
export const departmentsApi = {
  // Get all departments with optional filtering
  async getDepartments(params: {
    page?: number;
    limit?: number;
    search?: string;
    include_inactive?: boolean;
    organization_id?: number;
  } = {}): Promise<ApiResponse<DepartmentsListResponse>> {
    const queryParams = new URLSearchParams();
    
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.limit) queryParams.append('limit', params.limit.toString());
    if (params.search) queryParams.append('search', params.search);
    if (params.include_inactive !== undefined) queryParams.append('include_inactive', params.include_inactive.toString());
    if (params.organization_id !== undefined) queryParams.append('organization_id', params.organization_id.toString());

    const endpoint = `/departments${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<DepartmentsListResponse>(endpoint);
  },

  // Get department by ID
  async getDepartment(id: number): Promise<ApiResponse<{ department: Department }>> {
    return apiRequest<{ department: Department }>(`/departments/${id}`);
  },

  // Get departments for dropdown (simplified version)
  async getDepartmentsForDropdown(): Promise<ApiResponse<Department[]>> {
    try {
      const response = await this.getDepartments({ limit: 100, include_inactive: false });
      
      if (response.status === 'success' && response.data) {
        return {
          status: 'success',
          message: 'Departments fetched successfully',
          data: response.data.departments
        };
      }
      
      return {
        status: 'error',
        message: response.message || 'Failed to fetch departments'
      };
    } catch (error) {
      console.error('Departments API error:', error);
      throw error;
    }
  },

  // Create new department
  async createDepartment(data: {
    name: string;
    order_id?: number;
    description?: string;
    parent_id?: number | null;
    organization_id?: number;
  }): Promise<ApiResponse<Department>> {
    return apiRequest<Department>('/departments', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  },

  // Update department
  async updateDepartment(id: number, data: {
    name: string;
    order_id?: number;
    description?: string;
    parent_id?: number | null;
  }): Promise<ApiResponse<Department>> {
    return apiRequest<Department>(`/departments/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  },

  // Delete department
  async deleteDepartment(id: number): Promise<ApiResponse<{ message: string }>> {
    try {
      console.log(`Attempting to delete department with ID: ${id}`);
      
      // For DELETE requests, we might not get JSON response
      const response = await fetch(`${API_BASE_URL}/departments/${id}`, {
        method: 'DELETE',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'Authorization': `Bearer ${localStorage.getItem('authToken')}`,
        },
        mode: 'cors',
        credentials: 'omit',
      });
      
      console.log('Delete response status:', response.status);
      console.log('Delete response headers:', response.headers);
      
      if (!response.ok) {
        let errorMessage = `HTTP error! status: ${response.status}`;
        
        try {
          const errorData = await response.json();
          errorMessage = errorData.message || errorMessage;
        } catch {
          errorMessage = response.statusText || errorMessage;
        }
        
        throw new Error(errorMessage);
      }
      
      // Try to parse JSON response, but handle cases where there's no content
      let responseData;
      const contentType = response.headers.get('content-type');
      
      if (contentType && contentType.includes('application/json')) {
        try {
          responseData = await response.json();
        } catch {
          responseData = { message: 'Department deleted successfully' };
        }
      } else {
        responseData = { message: 'Department deleted successfully' };
      }
      
      console.log('Delete response data:', responseData);
      
      return {
        status: 'success',
        message: responseData.message || 'Department deleted successfully',
        data: responseData
      };
      
    } catch (error) {
      console.error('Delete department error:', error);
      throw error;
    }
  },
};

// Excel Upload API Types
export interface ExcelUploadResponse {
  totalRows: number;
  processedUsers: number;
  errors: Array<{
    row: number;
    error: string;
    data: Record<string, unknown>;
  }>;
  warnings: Array<{
    row: number;
    warning: string;
    data: Record<string, unknown>;
  }>;
  insertedUsers: number;
  skippedUsers: number;
  details: Array<{
    row: number;
    status: 'success' | 'error' | 'warning';
    message: string;
    userId?: number;
    data?: Record<string, unknown>;
  }>;
}

export interface LookupValuesResponse {
  ranks: Array<{ name: string; id: number }>;
  units: Array<{ name: string; id: number }>;
  departments: Array<{ name: string; id: number }>;
  roles: Array<{ name: string; id: number }>;
  designations: Array<{ name: string; id: number }>;
}

// Excel Upload API functions
export const excelUploadApi = {
  // Upload Excel file
  async uploadExcel(file: File): Promise<ApiResponse<ExcelUploadResponse>> {
    const formData = new FormData();
    formData.append('excelFile', file);

    const url = `${API_BASE_URL}/users/excel/upload`;
    const token = localStorage.getItem('authToken');
    
    if (!token) {
      throw new Error('Authentication token not found');
    }

    try {
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
        },
        body: formData,
        mode: 'cors',
        credentials: 'omit',
      });

      const data = await response.json();
      
      // Handle both HTTP errors and API-level errors
      if (!response.ok) {
        throw new Error(data.message || `HTTP error! status: ${response.status}`);
      }
      
      // Return data regardless of success/error status
      // The UI will handle displaying errors from data.details
      return data;
    } catch (error) {
      console.error('Excel upload error:', error);
      throw error;
    }
  },

  // Download Excel template
  async downloadTemplate(): Promise<void> {
    const url = `${API_BASE_URL}/users/excel/template`;
    const token = localStorage.getItem('authToken');
    
    if (!token) {
      throw new Error('Authentication token not found');
    }

    try {
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${token}`,
        },
        mode: 'cors',
        credentials: 'omit',
      });

      if (!response.ok) {
        throw new Error(`Failed to download template: ${response.statusText}`);
      }

      const blob = await response.blob();
      const urlObject = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = urlObject;
      a.download = 'user_upload_template.xlsx';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(urlObject);
    } catch (error) {
      console.error('Template download error:', error);
      throw error;
    }
  },

  // Get lookup values
  async getLookupValues(): Promise<ApiResponse<LookupValuesResponse>> {
    return apiRequest<LookupValuesResponse>('/users/excel/lookup-values');
  },
};

// Role Management API
export interface Role {
  id: number;
  name: string;
  description: string;
  level: number;
  is_active: number | boolean; // Allow both number and boolean
  created_at: string;
  updated_at: string;
  permissions?: string[];
  permission_ids?: number[];
  organization_id?: number;
  organization_name?: string;
  organization_code?: string;
}

export interface Permission {
  id: number;
  name: string;
  description: string;
  resource: string;
  action: string;
  is_active: number | boolean;
  created_at: string;
  updated_at: string;
  roles?: string[];
  role_ids?: number[];
}

export interface RoleCreateRequest {
  name: string;
  description: string;
  level: number;
  permissions?: number[];
}

export interface RoleUpdateRequest {
  name: string;
  description: string;
  level: number;
  permissions?: number[];
}

export interface RolesResponse {
  roles: Role[];
}

export interface PermissionsResponse {
  permissions: Permission[];
}

export interface RoleResponse {
  role: Role;
}

export interface PermissionResponse {
  permission: Permission;
}

// Role API functions
export const roleApi = {
  // Get all roles
  async getRoles(): Promise<ApiResponse<RolesResponse>> {
    return apiRequest<RolesResponse>('/roles');
  },

  // Get roles with permissions
  async getRolesWithPermissions(): Promise<ApiResponse<RolesResponse>> {
    return apiRequest<RolesResponse>('/roles');
  },

  // Get role by ID
  async getRoleById(id: number): Promise<ApiResponse<RoleResponse>> {
    return apiRequest<RoleResponse>(`/roles/${id}`);
  },

  // Get role with permissions by ID
  async getRoleWithPermissions(id: number): Promise<ApiResponse<RoleResponse>> {
    return apiRequest<RoleResponse>(`/roles/${id}/permissions`);
  },

  // Create new role
  async createRole(roleData: RoleCreateRequest): Promise<ApiResponse<RoleResponse>> {
    return apiRequest<RoleResponse>('/roles', {
      method: 'POST',
      body: JSON.stringify(roleData),
    });
  },

  // Update role
  async updateRole(id: number, roleData: RoleUpdateRequest): Promise<ApiResponse<RoleResponse>> {
    return apiRequest<RoleResponse>(`/roles/${id}`, {
      method: 'PUT',
      body: JSON.stringify(roleData),
    });
  },

  // Delete role
  async deleteRole(id: number): Promise<ApiResponse<{ message: string }>> {
    return apiRequest<{ message: string }>(`/roles/${id}`, {
      method: 'DELETE',
    });
  },

  // Get all permissions
  async getPermissions(): Promise<ApiResponse<PermissionsResponse>> {
    return apiRequest<PermissionsResponse>('/roles/permissions');
  },

  // Get permissions grouped by resource
  async getPermissionsGrouped(): Promise<ApiResponse<{ permissions: Record<string, Permission[]> }>> {
    return apiRequest<{ permissions: Record<string, Permission[]> }>('/roles/permissions/grouped');
  },

  // Get permissions with roles
  async getPermissionsWithRoles(): Promise<ApiResponse<PermissionsResponse>> {
    return apiRequest<PermissionsResponse>('/roles/permissions/with-roles');
  },

  // Permission CRUD operations
  async getPermissionById(id: number): Promise<ApiResponse<PermissionResponse>> {
    return apiRequest<PermissionResponse>(`/roles/permissions/${id}`);
  },

  async createPermission(permissionData: {
    name: string;
    description: string;
    resource: string;
    action: string;
  }): Promise<ApiResponse<PermissionResponse>> {
    return apiRequest<PermissionResponse>('/roles/permissions', {
      method: 'POST',
      body: JSON.stringify(permissionData),
    });
  },

  async updatePermission(id: number, permissionData: {
    name: string;
    description: string;
    resource: string;
    action: string;
  }): Promise<ApiResponse<PermissionResponse>> {
    return apiRequest<PermissionResponse>(`/roles/permissions/${id}`, {
      method: 'PUT',
      body: JSON.stringify(permissionData),
    });
  },

  async deletePermission(id: number): Promise<ApiResponse<{ message: string }>> {
    return apiRequest<{ message: string }>(`/roles/permissions/${id}`, {
      method: 'DELETE',
    });
  },
};

// Organizations API types and functions
export interface Organization {
  id: number;
  name: string;
  code?: string;
}

export interface OrganizationsListResponse {
  organizations: Organization[];
  statistics?: any;
  pagination?: any;
}

export const organizationsApi = {
  async getOrganizations(params: {
    page?: number;
    limit?: number;
    search?: string;
    is_active?: string;
    type?: string;
  } = {}): Promise<ApiResponse<OrganizationsListResponse>> {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', String(params.page));
    if (params.limit) queryParams.append('limit', String(params.limit));
    if (params.search) queryParams.append('search', params.search);
    if (params.is_active !== undefined) queryParams.append('is_active', String(params.is_active));
    if (params.type) queryParams.append('type', params.type);
    const qs = queryParams.toString();
    return apiRequest<OrganizationsListResponse>(`/organizations${qs ? `?${qs}` : ''}`);
  },
  async getMyOrganization(): Promise<ApiResponse<{ organization: Organization }>> {
    return apiRequest<{ organization: Organization }>(`/organizations/my-organization`);
  }
};

export interface Country {
  id: number;
  name: string;
  code?: string | null;
  is_active: number | boolean;
  created_at: string;
  updated_at: string;
}

export const countriesApi = {
  async getCountries(params: {
    page?: number;
    limit?: number;
    search?: string;
    include_inactive?: boolean;
  } = {}): Promise<ApiResponse<Country[]>> {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', String(params.page));
    if (params.limit) queryParams.append('limit', String(params.limit));
    if (params.search) queryParams.append('search', params.search);
    if (params.include_inactive !== undefined) queryParams.append('include_inactive', String(params.include_inactive));
    const qs = queryParams.toString();
    return apiRequest<Country[]>(`/countries${qs ? `?${qs}` : ''}`);
  },
  async getCountry(id: number): Promise<ApiResponse<Country>> {
    return apiRequest<Country>(`/countries/${id}`);
  },
  async createCountry(data: { name: string; code?: string }): Promise<ApiResponse<Country>> {
    return apiRequest<Country>('/countries', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  },
  async updateCountry(id: number, data: { name?: string; code?: string; is_active?: boolean }): Promise<ApiResponse<Country>> {
    return apiRequest<Country>(`/countries/${id}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  },
  async deleteCountry(id: number): Promise<ApiResponse<{ message: string }>> {
    return apiRequest<{ message: string }>(`/countries/${id}`, {
      method: 'DELETE',
    });
  },
};

export interface Division {
  id: number;
  country_id: number;
  name: string;
  code?: string | null;
  is_active: number | boolean;
  created_at: string;
  updated_at: string;
  country_name?: string;
}

export interface District {
  id: number;
  division_id: number;
  name: string;
  code?: string | null;
  is_active: number | boolean;
  created_at: string;
  updated_at: string;
  division_name?: string;
}

export interface Thana {
  id: number;
  district_id: number;
  name: string;
  code?: string | null;
  is_active: number | boolean;
  created_at: string;
  updated_at: string;
  district_name?: string;
}

export const locationsApi = {
  async getDivisions(params: {
    page?: number;
    limit?: number;
    search?: string;
    country_id?: number;
    include_inactive?: boolean;
  } = {}): Promise<ApiResponse<Division[]>> {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', String(params.page));
    if (params.limit) queryParams.append('limit', String(params.limit));
    if (params.search) queryParams.append('search', params.search);
    if (typeof params.country_id === 'number') queryParams.append('country_id', String(params.country_id));
    if (params.include_inactive !== undefined) queryParams.append('include_inactive', String(params.include_inactive));
    const qs = queryParams.toString();
    return apiRequest<Division[]>(`/locations/divisions${qs ? `?${qs}` : ''}`);
  },

  async getDistricts(params: {
    page?: number;
    limit?: number;
    search?: string;
    division_id?: number;
    include_inactive?: boolean;
  } = {}): Promise<ApiResponse<{ districts: District[]; total: number }>> {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', String(params.page));
    if (params.limit) queryParams.append('limit', String(params.limit));
    if (params.search) queryParams.append('search', params.search);
    if (typeof params.division_id === 'number') queryParams.append('division_id', String(params.division_id));
    if (params.include_inactive !== undefined) queryParams.append('include_inactive', String(params.include_inactive));
    const qs = queryParams.toString();
    return apiRequest<{ districts: District[]; total: number }>(`/locations/districts${qs ? `?${qs}` : ''}`);
  },

  async getThanas(params: {
    page?: number;
    limit?: number;
    search?: string;
    district_id?: number;
    include_inactive?: boolean;
  } = {}): Promise<ApiResponse<{ thanas: Thana[]; total: number }>> {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', String(params.page));
    if (params.limit) queryParams.append('limit', String(params.limit));
    if (params.search) queryParams.append('search', params.search);
    if (typeof params.district_id === 'number') queryParams.append('district_id', String(params.district_id));
    if (params.include_inactive !== undefined) queryParams.append('include_inactive', String(params.include_inactive));
    const qs = queryParams.toString();
    return apiRequest<{ thanas: Thana[]; total: number }>(`/locations/thanas${qs ? `?${qs}` : ''}`);
  },
};

// Import messaging API
import { messagingApi } from './messagingApi';

// Export messaging API
export { messagingApi };

export default authApi;
