import { AxiosInstance } from 'axios'
import { HealthStatus } from '../common/types'
import {
	GetExportedValidatorsQuery,
	ValidatorWithWallet,
	ValidatorToken,
	CreateValidator,
	Validator,
	ValidatorId,
} from './types'

import { getStringifiedQuery } from '../common/query'
import { OrganizerId } from '../account'

/**
 * Service class for validator API calls.
 */
export class ValidatorService {
	constructor(readonly client: AxiosInstance, readonly version: string) {}

	/**
	 * Returns true if the service is reachable
	 *
	 * @returns Services' online status
	 */
	async health(): Promise<HealthStatus> {
		try {
			const res = await this.client.get(`account/health`)
			if (res.data.status === 'ok') {
				return { online: true }
			}
		} catch (e) {
			// Do nothing
		}

		return { online: false }
	}

	/**
	 * Returns the validator using the given token
	 *
	 * @param token token for fetching the validator
	 * @returns Validator object
	 * @throws `NotFoundError`
	 */
	async getValidatorByToken(
		token: ValidatorToken
	): Promise<ValidatorWithWallet> {
		const res = await this.client.get(
			`account/${this.version}/organizer/validator/${token.token}`
		)

		return res.data.data
	}

	async getExportedValidators(
		id: OrganizerId,
		query: GetExportedValidatorsQuery
	): Promise<ValidatorWithWallet[]> {
		const queryStringified = getStringifiedQuery({
			event_id: query.event_id,
		})

		const res = await this.client.get(
			`account/${this.version}/organizer/${id.id}/validator/export?${queryStringified}`
		)

		return res.data.data
	}

	/**
	 * Creates a new user which can validate tickets for the specified org.
	 * @param organizerId.id Name or ID of the organizer to whom the validator belongs to
	 * @param validator Validator data (eventId which signals for which event is the validator)
	 * @returns new Validator
	 */
	async createValidator(
		organizerId: OrganizerId,
		validator: CreateValidator
	): Promise<Validator> {
		const res = await this.client.post(
			`account/${this.version}/organizer/${organizerId.id}/validator`,
			validator
		)
		return res.data.data
	}

	/**
	 * Fetches validator data.
	 * @param id.organizerId Name or ID of the organizer to whom the validator belongs to
	 * @param id.id ID of the validator to be fetched
	 * @returns requested Validator
	 */
	async getValidator(id: ValidatorId): Promise<Validator> {
		const res = await this.client.get(
			`account/${this.version}/organizer/${id.organizerId}/validator/${id.id}`
		)

		return res.data.data
	}
}
