/*
 * Copyright (c) 2023 Eclipse Foundation, Inc.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * Contributors:
 *   Olivier Goulet <olivier.goulet@eclipse-foundation.org>
 *
 * SPDX-License-Identifier: EPL-2.0
 */

import 'isomorphic-fetch';
import { Organization } from '../types/models';
import { APIResponse, HttpError } from '../types/api';
import { convertToQueryString, transformSnakeToCamel } from '../utils/utils';

const apiBasePath = 'https://membership.eclipse.org/api';

/**
  * Maps the snake case API response to camel case. 
  *
  * @param data - The API response.
  */
export const organizationMapper = (data: unknown): Organization => {
  return transformSnakeToCamel(data);
}

/**
  * Fetches an organization by id.
  * @param organizationId - The organization id.
  * @returns An error or the fetched organization.
  */
export const getOrganizationById = async (organizationId: number): Promise<APIResponse<Organization>> => {
  try {
    // Validate the organization id parameter.
    if (organizationId === undefined) {
      throw new TypeError('No organization id provided for fetching organization');
    } else if (typeof organizationId !== 'number') {
      throw new TypeError('The organization id must be a valid number');
    }

    const response = await fetch(`${apiBasePath}/organizations/${organizationId}`);
    if (!response.ok) throw new HttpError(response.status, `Could not fetch organization by id ${organizationId}`);

    const data = await response.json();
    const organization = organizationMapper(data);

    return [organization, null];
  } catch (error) {
    console.error(error);
  
    const errorResponse = {
      code: error.code,
      message: error.message,
    };

    return [null, errorResponse];
  }
};

export const getOrganizations = async (params = {}): Promise<APIResponse<Organization[]>> => {
  try {
    const queryString = convertToQueryString(params); 
    const response = await fetch(`${apiBasePath}/organizations?${queryString}`);
    if (!response.ok) {
      throw new HttpError(response.status, 'Could not fetch organizations');
    }

    const data = await response.json();
    const organizations: Organization[] = data
      .map(organizationMapper)
    
    return [organizations, null];
  } catch (error) {
    console.error(error);
    
    const errorResponse = {
      code: error.code,
      message: error.message,
    };

    return [null, errorResponse];
  }
}

export const getProjectParticipatingOrganizations = async (projectId: string, params = {}): Promise<APIResponse<unknown>> => {
  try {
    if (!projectId) {
        throw new Error('No project id provided for fetching project participating organizations');
    }

    const queryString = convertToQueryString(params);
    const response = await fetch(`${apiBasePath}/projects/${projectId}/organizations?${queryString}`);
    if (!response.ok) { 
        throw new HttpError(response.status, `Could not fetch project organizations for project id "${projectId}"`);
    }

    const data = await response.json();
    const organizations = data
        .map(organizationMapper)
        .sort((a: Organization, b: Organization) => a.name.localeCompare(b.name));

    return [organizations, null];
  } catch (error) {
    console.error(error);
    
    const errorResponse = {
      code: error.code,
      message: error.message,
    };

    return [null, errorResponse];
  }
};
