import { AxiosInstance } from 'axios';

interface IAuthBase {
  userName?: string
  password?: string
}

interface IAuthToken {
  /** Открытый ключ, который можно использовать для регистрации заказа.
   * Если для аутентификации при регистрации заказа используются логин и пароль, параметр token передавать не нужно */
  token?: string
}

interface IAuth extends IAuthBase, IAuthToken {}

type ErrorResponse = {
  /**Код ошибки */
  errorCode?: string | number

  /** Описание ошибки на языке, переданном в параметре language в запросе. */
  errorMessage?: string
}

interface Language {
  language?: string
}

/** Запрос регистрации заказа */
interface Register {
  /** Номер (идентификатор) заказа в системе магазина, уникален для каждого магазина в пределах системы */
  orderNumber: string

  /** Сумма платежа в копейках (или центах) */
  amount: number

  /**Код валюты платежа ISO 4217. Если не указано, то используется значение по умолчанию. */
  currency?: string

  /** Адрес, на который требуется перенаправить пользователя в случае успешной оплаты. Адрес должен быть указан
   * полностью, включая используемый протокол (например, https://test.ru вместо test.ru). */
  returnUrl: string

  /** Адрес, на который требуется перенаправить пользователя в случае неуспешной оплаты.
   * Адрес должен быть указан полностью, включая используемый протокол (например, https://test.ru вместо test.ru).
   * В противном случае пользователь будет перенаправлен по адресу следующего вида: http://<адрес_платёжного_шлюза>/<адрес_продавца>.
   * */
  failUrl?: string

  /** Описание заказа в свободной форме. (Чтобы получить возможность отправлять это поле в процессинг, обратитесь в техническую поддержку.) */
  description?: string

  /** Язык в кодировке ISO 639-1. Если не указан, будет использован язык, указанный в настройках магазина как язык по умолчанию. */
  language?: string

  /** По значению данного параметра определяется, какие страницы платёжного интерфейса должны загружаться для клиента */
  pageView?: 'DESKTOP' | 'MOBILE' | string

  /** Номер (идентификатор) клиента в системе магазина. Используется для реализации функционала связок. Может присутствовать, если магазину разрешено создание связи */
  clientId?: string

  /** Чтобы зарегистрировать заказ от имени дочернего мерчанта, укажите его логин в этом параметре. */
  merchantLogin?: string

  /** Блок для передачи дополнительных параметров мерчанта.
   *  Включение данного функционала возможно по согласованию с банком в период интеграции.
   */
  jsonParams?: {
    email?: string
    phone?: string
  } & {
    [K: string]: any
  }

  /** Продолжительность жизни заказа в секундах.
   * В случае если параметр не задан, будет использовано значение, указанное в настройках мерчанта или время по умолчанию (1200 секунд = 20 минут).
   * Если в запросе присутствует параметр expirationDate, то значение параметра sessionTimeoutSecs не учитывается. */
  sessionTimeoutSecs?: number

  /**Дата и время окончания жизни заказа. Формат: yyyy-MM-dd'T'HH:mm:ss.
   * Если этот параметр не передаётся в запросе, то для определения времени окончания жизни заказа используется sessionTimeoutSecs . */
  expirationDate?: string

  /**Идентификатор связки, созданной ранее. Может использоваться, только если у магазина есть разрешение на работу
   * со связками. Если этот параметр передаётся в данном запросе, то это означает:
   * 1. Данный заказ может быть оплачен только с помощью связки;
   * 2. Плательщик будет перенаправлен на платёжную страницу, где требуется только ввод CVC. */
  bindingId?: string

  /** Контейнер для параметра feature, в котором можно указать следующие значения.
   * AUTO_PAYMENT - Если запрос на регистрацию заказа инициирует проведение автоплатежей.
   * FORCE_TDS - Принудительное проведение платежа с использованием 3-D Secure. Если карта не поддерживает 3-D Secure, транзакция не пройдёт.
   * FORCE_SSL - Принудительное проведение платежа через SSL (без использования 3-D Secure).
   * FORCE_FULL_TDS - После проведения аутентификации с помощью 3-D Secure статус PaRes должен быть только Y, что гарантирует успешную аутентификацию пользователя. В противном случае транзакция не пройдёт. */
  features?: string

  /** Электронная почта покупателя. */
  email?: string

  /** Номер телефона покупателя в следующем формате: +375333333333. */
  phone?: string

  /** Блок, содержащий Корзину товаров заказа. */
  orderBundle?: orderBundle
}

interface orderBundle {
  /** Дата создания заказа */
  orderCreationDate?: string

  /** Блок с атрибутами данных о покупателе. */
  customerDetails?: {
    email?: string
    phone?: string
    contact?: string

    /** Блок с атрибутами адреса для доставки. */
    deliveryInfo?: {
      deliveryType?: string
      country: string
      city: string
      postAddress: string
    }
  }

  /** Блок с атрибутами товарных позиции Корзины.  */
  cartItems: {
    /** Элемент массива с атрибутами товарной позиции в Корзине */
    items?: cartItems[]
  }
}

interface cartItems {
  /** Уникальный идентификатор товарной позиции внутри Корзины Заказа */
  positionId: number
  /** name да Наименование или описание товарной позиции в свободной форме */
  name: string

  /** Дополнительный блок с параметрами описания товарной позиции. */
  itemDetails?: {
    /** Параметр описывающий дополнительную информацию по товарной позиции. */
    itemDetailsParams: {
      /** Дополнительная информация по товарной позиции */
      value: string
      /** Наименование параметра описания детализации товарной позиции */
      name: string
    }[]
  }

  /** Элемент описывающий общее количество товарных позиций одного positionId и их меру измерения. */
  quantity: {
    /** Количество товарных позиций данного positionId. Для указания дробных чисел используйте десятичную точку. */
    value: number

    /** Мера измерения количества товарной позиции
     * @example pieces
     */
    measure: string
  }

  /** Сумма стоимости всех товарных позиций одного positionId в минимальных единицах валюты.
   * `itemAmount` обязателен к передаче, только если не был передан параметр `itemPrice`. В противном случае передача `itemAmount`
   * не требуется.
   * Если же в запросе передаются оба параметра: `itemPrice` и `itemAmount`, то `itemAmount` должен
   * равняться `itemPrice * quantity`, в противном случае запрос завершится с ошибкой.*/
  itemAmount?: number

  /** Сумма стоимости 1 товарной позиций одного positionId в минимальных единицах валюты */
  itemPrice?: number

  itemCurrency?: number

  /** Номер (идентификатор) товарной позиции в системе магазина. Параметр должен быть уникальным в рамках запроса. */
  itemCode: string

  discount?: {
    /** Тип скидки на товарную позицию
     * @example percent
     */
    discountType: string
    /** Значение скидки на товарную позицию */
    discountValue: number
  }
  agentInterest?: {
    /** Тип агентской комиссии за продажу товара */
    interestType: string
    /** Значение агентской комиссии за продажу товара */
    interestValue: string
  }
}

interface RegisterResponse extends ErrorResponse {
  /** Номер заказа в платежной системе. Уникален в пределах системы.
   * Отсутствует, если регистрация заказа на удалась по причине ошибки, детализированной в errorCode. */
  orderId?: string

  /** URL платежной формы, на который надо перенаправить браузер клиента.
   * Не возвращается, если регистрация заказа не удалась по причине ошибки, детализированной в errorCode. */
  formUrl?: string
}

/** Запрос регистрации заказа */
interface Refund {
  /** Номер заказа в платежной системе. Уникален в пределах системы */
  orderId: string

  /** Сумма возврата в копейках (или центах) */
  amount: number
}

interface RefundResponse extends ErrorResponse {
  /** Номер заказа в платежной системе. Уникален в пределах системы. */
  orderId?: string
}

declare enum OrderStatus {
    CREATED = 0,
    APPROVED = 1,
    DEPOSITED = 2,
    REVERSED = 3,
    REFUNDED = 4,
    AUTHORIZATION_INITIALIZED = 5,
    DECLINED = 6
}

/** Запрос состояния заказа */
interface Status {
  /** Номер заказа в платежной системе. Уникален в пределах системы */
  orderId: string

  /** Язык в кодировке ISO 639-1. Если не указан, считается, что язык – русский. Сообщение ошибке будет возвращено именно на этом языке. */
  language?: string
}

interface StatusResponse extends ErrorResponse {
  /** По значению этого параметра определяется состояние заказа в платежной системе. Список возможных значений приведен в таблице ниже. Отсутствует, если заказ не был найден. */
  OrderStatus?: OrderStatus

  /** Номер (идентификатор) заказа в системе магазина */
  OrderNumber: string

  /** Маскированный номер карты, которая использовалась для оплаты. Указан только после оплаты заказа. */
  Pan?: number

  /** Срок истечения действия карты в формате YYYYMM. Указан только после оплаты заказа. */
  expiration?: number

  /** Имя держателя карты. Указан только после оплаты заказа. */
  cardholderName?: string

  /** Сумма платежа в копейках (или центах) */
  Amount: number

  /** Код валюты платежа ISO 4217. Если не указано, то используется значение по умолчанию. */
  currency?: number

  /** Код авторизации МПС. Поле фиксированной длины (6 символов), может содержать цифры и латинские буквы. */
  approvalCode?: string

  /** Это поле является устаревшим. Его значение всегда равно "2", независимо от состояния заказа и кода авторизации процессинговой системы. */
  authCode?: number

  /** IP-адрес пользователя, который оплачивал заказ. */
  Ip?: string
}

interface StatusExtended extends Status {
  /** Номер (идентификатор) заказа в системе магазина.
   *
   * - В запросе должен присутствовать либо `orderId`, либо `orderNumber`.
   * - Если в запросе присутствуют оба параметра, то приоритетным считается `orderId`.
   */
  orderNumber?: string
}

interface Mutated {
  /** Оплачен ли платеж  */
  paid: boolean

  /** object converted parameters  */
  params: { [K: string]: any }
}

interface StatusExtendedResponse extends ErrorResponse, Mutated {
  /** Номер (идентификатор) заказа в системе магазина. */
  orderNumber: string

  orderStatus?: OrderStatus

  /** Код ответа. */
  actionCode: number

  /** Расшифровка кода ответа на языке, переданном в параметре Language в запросе. */
  actionCodeDescription: string

  /** Сумма платежа в копейках (или центах) */
  amount: number

  /** Код валюты платежа ISO 4217. Если не указано, то используется значение по умолчанию. */
  currency?: string

  /** Дата регистрации заказа.  */
  date: number

  /** Описание заказа, переданное при его регистрации  */
  orderDescription?: string

  /** IP-адрес пользователя, который оплачивал заказ.  */
  ip: string

  /** Учётный номер авторизации платежа, который присваивается при регистрации платежа. */
  authRefNum: string

  /** Дата и время возврата средств.  */
  refundedDate?: string

  /** Дополнительные параметры продавца */
  merchantOrderParams?: Attribute[]

  cardAuthInfo: CardAuthInfo

  secureAuthInfo?: {
    /** Электронный коммерческий индикатор. Указан только после оплаты заказа и в случае
     * соответствующего разрешения. */
    eci?: number
    /** Значение проверки аутенфикации владельца карты. Указан только после оплаты заказа и в случае соответствующего разрешения. */
    cavv?: string
    /** Электронный коммерческий идентификатор транзакции. Указан только после оплаты заказа и в случае соответствующего разрешения. */
    xid?: string
  }

  bindingInfo?: BindingInfo
  paymentAmountInfo: PaymentAmountInfo
  bankInfo: BankInfo

  // TODO:
  transactionAttributes: any[]
  attributes: Attribute[]
  authDateTime: number
  terminalId: string
  orderBundle: OrderBundle
}

// TODO:
interface BindingInfo {
  clientId?: string
  bindingId?: string
  authDateTime?: string
  terminalId?: string
}

// TODO:
interface Attribute {
  name: string
  value: string
}

// TODO:
interface BankInfo {
  bankCountryCode: string
  bankCountryName: string
}

// TODO:
interface CardAuthInfo {
  maskedPan: string
  expiration: string
  cardholderName: string
  approvalCode: string
  pan: string
}

// TODO:
interface OrderBundle {
  customerDetails: CustomerDetails
  cartItems: CartItems
}

interface CartItems {
  items: Item[]
}

// TODO:
interface Item {
  positionId: string
  name: string
  quantity: Quantity
  itemAmount: number
  itemCurrency: number
  itemCode: string
}

interface Quantity {
  value: number
  measure: string
}

interface CustomerDetails {
  email: string
  phone: string
}

// TODO:
interface PaymentAmountInfo {
  paymentState?: string
  approvedAmount?: number
  depositedAmount?: number
  refundedAmount?: number
}

interface Params extends Language {
  /** Номер заказа в платежной системе. Уникален в пределах системы. */
  orderId: string

  /** Поля для передачи дополнительных параметров, вида {"param":"value","param2":"value2"}  */
  params: {
    [K: string]: any
  }
}

interface ParamsResponse extends ErrorResponse {}

interface Options extends IAuth {
    language?: string;
}
declare const useAlfaBank: ({ token, password, userName, language, }?: Options) => {
    instance: AxiosInstance;
    register: (data: Register) => Promise<RegisterResponse | null>;
    refund: (data: Refund) => Promise<RefundResponse | null>;
    addParams: (data: Params) => Promise<true | ParamsResponse | null>;
    getOrderStatus: (data: Status) => Promise<StatusResponse | null>;
    getOrderStatusExtended: (data: StatusExtended) => Promise<StatusExtendedResponse | null>;
};

/**
 * Функция для конвертирование в минимальных единицах
 * С учетом проблем плавающей точки
 * 10.20 - 1020
 */
declare const toBynPenny: (value: number) => number;

export { Attribute, IAuth, IAuthBase, IAuthToken, Refund, RefundResponse, Register, RegisterResponse, Status, StatusExtended, StatusExtendedResponse, StatusResponse, toBynPenny, useAlfaBank };
