<?php
namespace Fifa\ConnectId\Sdk\ApiClient\Person;

use DateTime;
use Fifa\ConnectId\Sdk\Api\Model\AddRegistrationsRequestType;
use Fifa\ConnectId\Sdk\Api\Model\BulkDeactivateRegistrationsRequestType;
use Fifa\ConnectId\Sdk\Api\Model\BulkDeactivateRegistrationsResponseType;
use Fifa\ConnectId\Sdk\Api\Model\GetDuplicatesOfRegisteredPersonResponseType;
use Fifa\ConnectId\Sdk\Api\Model\PersonDuplicateType;
use Fifa\ConnectId\Sdk\Api\Model\PersonType;
use Fifa\ConnectId\Sdk\Api\Model\RegistrationType;
use Fifa\ConnectId\Sdk\Api\Model\UpdateRegistrationsRequestType;
use Fifa\ConnectId\Sdk\Exception\FifaConflictException;
use Fifa\ConnectId\Sdk\Exception\FifaConnectIdException;
use Fifa\ConnectId\Sdk\Exception\FifaDuplicatedPersonFoundException;
use Fifa\ConnectId\Sdk\Exception\FifaDuplicateOfRegisteredPersonFoundException;
use Fifa\ConnectId\Sdk\Exception\FifaEntityNotFoundException;
use Fifa\ConnectId\Sdk\Exception\FifaPersonMergedException;
use Fifa\ConnectId\Sdk\Exception\InvalidClientDataException;
use Fifa\ConnectId\Sdk\Exception\TooManyRequestsException;
use Fifa\ConnectId\Sdk\Model\PersonData;
use Fifa\ConnectId\Sdk\Model\PersonName;
use Fifa\ConnectId\Sdk\Registration\ValidationException;
use Fifa\ConnectServiceBus\Sdk\Exception\AuthenticationException;
use Fifa\ConnectServiceBus\Sdk\Exception\UnauthorizedException;
use InvalidArgumentException;

/**
 * Interface PersonApiInterface
 * @package Fifa\ConnectId\Sdk\ApiClient\Person
 */
interface PersonApiInterface
{
    /**
     * Gets person data associated with the specified FIFA Unique Identifier.
     *
     * @param string $fifaId - FIFA Unique Identifier
     * @return PersonType
     *
     * @throws InvalidClientDataException
     * @throws FifaEntityNotFoundException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws FifaPersonMergedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function getPersonData(string $fifaId): PersonType;

    /**
     * Gets data of the registration belonging to the primary data provider of the specified FIFA Unique Identifier.
     *
     * @param string $fifaId - FIFA Unique Identifier
     * @return RegistrationType
     *
     * @throws InvalidClientDataException
     * @throws FifaEntityNotFoundException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws FifaPersonMergedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function getPrimaryDataProviderRegistration(string $fifaId): ?RegistrationType;

    /**
     * Gets a list of people this person may be duplicated with.
     * Uses 'PersonLocalType' as defined in FIFA Data Standard.
     *
     * @param PersonData $personData - object containing information about local and international names of the person, as well as the date of birth.
     * @param string[]|null $organisationsIds - Organisations FIFA Unique Identifiers
     * @return PersonDuplicateType[]
     *
     * @throws InvalidClientDataException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function getDuplicates(PersonData $personData, ?array $organisationsIds = null): array;

    /**
     * Gets a list of people this person may be duplicated with.
     * Duplicates marked as known duplicate by trusted organisations would not be returned.
     *
     * @param string $personFifaId
     * @param string[]|null $trustedOrganisationsIds
     * @return GetDuplicatesOfRegisteredPersonResponseType
     *
     * @throws InvalidClientDataException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function getDuplicatesExceptTrustedKnownDuplicates(string $personFifaId, ?array $trustedOrganisationsIds = null): GetDuplicatesOfRegisteredPersonResponseType;

    /**
     * Registers a new person and assigns FIFA Unique Identifier.
     * If duplicates are found the person is not registered.
     * Uses 'PersonLocalType' as defined in FIFA Data Standard.
     *
     * @param PersonData $personData - object containing information about local and international names of the person, as well as the date of birth.
     * @param string|null $personLocalId - Local identifier of person
     * @return string FifaId
     *
     * @throws InvalidClientDataException
     * @throws FifaDuplicatedPersonFoundException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function register(PersonData $personData, ?string $personLocalId = null): string;

    /**
     * Registers a new person even if possible duplicates are found.
     * Uses 'PersonLocalType' as defined in FIFA Data Standard.
     * 
     * @param PersonData $personData - object containing information about local and international names of the person, as well as the date of birth.
     * @param string|null $personLocalId - Local identifier of person
     * @return string FifaId
     *
     * @throws InvalidClientDataException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function forceRegister(PersonData $personData, ?string $personLocalId = null): string;

    /**
     * Method adds registrations into person
     *
     * @param AddRegistrationsRequestType $request
     * @param bool $force
     * @return PersonType
     *
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function addRegistrations(AddRegistrationsRequestType $request, bool $force): PersonType;

    /**
     * Method updates registrations for a person
     *
     * @param UpdateRegistrationsRequestType $request
     * @param bool $force
     * @return PersonType
     *
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws InvalidClientDataException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function updateRegistrations(UpdateRegistrationsRequestType $request, bool $force): PersonType;

    /**
     * Updates person data.
     *
     * @param string $fifaId
     * @param PersonName[] $names . Null if not changed
     * @param DateTime|null $dateOfBirth . Null if not changed
     * @param string|null $gender
     * @param bool $forceUpdate
     * @return PersonType
     *
     * @throws InvalidClientDataException
     * @throws FifaEntityNotFoundException
     * @throws FifaConnectIdException
     * @throws FifaDuplicateOfRegisteredPersonFoundException
     * @throws InvalidArgumentException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function updatePerson(string $fifaId, ?array $names = null, ?DateTime $dateOfBirth = null, ?string $gender = null, bool $forceUpdate = false): PersonType;

    /**
     * Merges two persons. Returns the primary person.
     *
     * @param string $primaryPersonId - Primary person FIFA Unique Identifier
     * @param string $secondaryPersonId - Secondary person FIFA Unique Identifier
     * @return PersonType
     *
     * @throws InvalidClientDataException
     * @throws FifaEntityNotFoundException
     * @throws FifaConflictException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function mergePersons(string $primaryPersonId, string $secondaryPersonId): PersonType;

    /**
     * Reverts merge operation. Returns the secondary person which will be active again when unmerge operations is completed.
     *
     * @param $primaryPersonId - Primary person FIFA Unique Identifier
     * @param $secondaryPersonId - Secondary person FIFA Unique Identifier
     * @return PersonType
     *
     * @throws InvalidClientDataException
     * @throws FifaEntityNotFoundException
     * @throws FifaConflictException
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function unmergePersons(string $primaryPersonId, string $secondaryPersonId): PersonType;

    /**
     * Bulk deactivate registrations given in request.
     *
     * @param BulkDeactivateRegistrationsRequestType $request
     * @return BulkDeactivateRegistrationsResponseType
     *
     * @throws FifaConnectIdException
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws InvalidClientDataException
     * @throws ValidationException
     * @throws TooManyRequestsException
     */
    public function bulkDeactivateRegistrations(BulkDeactivateRegistrationsRequestType $request): BulkDeactivateRegistrationsResponseType;

    /**
     * Gets secondary FIFA IDs directly merged into person
     *
     * @param string $personFifaId
     * @return string[]
     *
     * @throws UnauthorizedException
     * @throws AuthenticationException
     * @throws InvalidClientDataException
     * @throws FifaEntityNotFoundException
     * @throws ValidationException
     * @throws TooManyRequestsException
     * @throws FifaConnectIdException
     */
    public function getMergedSecondaryFifaIdsForPerson(string $personFifaId): array;
}