/*
 * This file is part of LibEuFin.
 * Copyright (C) 2024-2025 Taler Systems S.A.
 *
 * LibEuFin is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3, or
 * (at your option) any later version.
 *
 * LibEuFin is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
 * Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with LibEuFin; see the file COPYING.  If not, see
 * <http://www.gnu.org/licenses/>
 */

package tech.libeufin.common

import kotlinx.serialization.*

enum class IncomingType {
    reserve,
    kyc,
    wad
}

enum class TransferStatusState {
    pending,
    transient_failure,
    permanent_failure,
    success
}

/** Response GET /taler-wire-gateway/config */
@Serializable
data class WireGatewayConfig(
    val currency: String,
    val support_account_check: Boolean
) {
    val name: String = "taler-wire-gateway"
    val version: String = WIRE_GATEWAY_API_VERSION
}

/** Request POST /taler-wire-gateway/transfer */
@Serializable
data class TransferRequest(
    val request_uid: HashCode,
    val amount: TalerAmount,
    val exchange_base_url: ExchangeUrl,
    val wtid: ShortHashCode,
    val credit_account: Payto
)

/** Response POST /taler-wire-gateway/transfer */
@Serializable
data class TransferResponse(
    val timestamp: TalerProtocolTimestamp,
    val row_id: Long
)

/** Request GET /taler-wire-gateway/transfers */
@Serializable
data class TransferList(
    val transfers: List<TransferListStatus>,
    val debit_account: String
)
@Serializable
data class TransferListStatus(
    val row_id: Long,
    val status: TransferStatusState,
    val amount: TalerAmount,
    val credit_account: String,
    val timestamp: TalerProtocolTimestamp
)

/** Request GET /taler-wire-gateway/transfers/{ROW_iD} */
@Serializable
data class TransferStatus(
    val status: TransferStatusState,
    val status_msg: String? = null,
    val amount: TalerAmount,
    val origin_exchange_url: String,
    val wtid: ShortHashCode,
    val credit_account: String,
    val timestamp: TalerProtocolTimestamp
)

/** Request POST /taler-wire-gateway/admin/add-incoming */
@Serializable
data class AddIncomingRequest(
    val amount: TalerAmount,
    val reserve_pub: EddsaPublicKey,
    val debit_account: Payto
)

/** Response POST /taler-wire-gateway/admin/add-incoming */
@Serializable
data class AddIncomingResponse(
    val timestamp: TalerProtocolTimestamp,
    val row_id: Long
)

/** Request POST /taler-wire-gateway/admin/add-kycauth */
@Serializable
data class AddKycauthRequest(
    val amount: TalerAmount,
    val account_pub: EddsaPublicKey,
    val debit_account: Payto
)

/** Response GET /taler-wire-gateway/history/incoming */
@Serializable
data class IncomingHistory(
    val incoming_transactions: List<IncomingBankTransaction>,
    val credit_account: String
)

/** Inner response GET /taler-wire-gateway/history/incoming */
@Serializable
sealed interface IncomingBankTransaction {
    val row_id: Long
    val date: TalerProtocolTimestamp
    val amount: TalerAmount
    val debit_account: String
    val credit_fee: TalerAmount?
}

@Serializable
@SerialName("KYCAUTH")
data class IncomingKycAuthTransaction(
    override val row_id: Long,
    override val date: TalerProtocolTimestamp,
    override val amount: TalerAmount,
    override val credit_fee: TalerAmount? = null,
    override val debit_account: String,
    val account_pub: EddsaPublicKey
): IncomingBankTransaction
@Serializable
@SerialName("RESERVE")
data class IncomingReserveTransaction(
    override val row_id: Long,
    override val date: TalerProtocolTimestamp,
    override val amount: TalerAmount,
    override val credit_fee: TalerAmount? = null,
    override val debit_account: String,
    val reserve_pub: EddsaPublicKey
): IncomingBankTransaction
@Serializable
@SerialName("WAD")
data class IncomingWadTransaction(
    override val row_id: Long,
    override val date: TalerProtocolTimestamp,
    override val amount: TalerAmount,
    override val credit_fee: TalerAmount? = null,
    override val debit_account: String,
    val origin_exchange_url: String,
    val wad_id: String // TODO 24 bytes Base32
): IncomingBankTransaction

/** Response GET /taler-wire-gateway/history/outgoing */
@Serializable
data class OutgoingHistory(
    val outgoing_transactions: List<OutgoingTransaction>,
    val debit_account: String
)

/** Inner response GET /taler-wire-gateway/history/outgoing */
@Serializable
data class OutgoingTransaction(
    val row_id: Long, // DB row ID of the payment.
    val date: TalerProtocolTimestamp,
    val amount: TalerAmount,
    val credit_account: String,
    val wtid: ShortHashCode,
    val exchange_base_url: String,
)

/** Response GET /taler-wire-gateway/account/check */
@Serializable
class AccountInfo()

/** Response GET /taler-revenue/config */
@Serializable
data class RevenueConfig(
    val currency: String
) {
    val name: String = "taler-revenue"
    val version: String = REVENUE_API_VERSION
}

/** Request GET /taler-revenue/history */
@Serializable
data class RevenueIncomingHistory(
    val incoming_transactions : List<RevenueIncomingBankTransaction>,
    val credit_account: String
)

/** Inner request GET /taler-revenue/history */
@Serializable
data class RevenueIncomingBankTransaction(
    val row_id: Long,
    val date: TalerProtocolTimestamp,
    val amount: TalerAmount,
    val credit_fee: TalerAmount? = null,
    val debit_account: String,
    val subject: String
)