/*
 * 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.nexus.cli

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.convert
import com.github.ajalt.clikt.parameters.groups.provideDelegate
import com.github.ajalt.clikt.parameters.options.convert
import com.github.ajalt.clikt.parameters.options.option
import tech.libeufin.common.*
import tech.libeufin.nexus.db.InitiatedPayment
import tech.libeufin.nexus.nexusConfig
import tech.libeufin.nexus.withDb
import tech.libeufin.ebics.randEbicsId
import java.time.Instant

class InitiatePayment: TalerCmd() {
    override fun help(context: Context) = "Initiate an outgoing payment"

    private val amount by option(
        "--amount",
        help = "The amount to transfer, payto 'amount' parameter takes the precedence"
    ).convert { TalerAmount(it) }
    private val subject by option(
        "--subject",
        help = "The payment subject, payto 'message' parameter takes the precedence"
    )
    private val endToEndId by option(
        "--end-to-end-id",
        "--request-uid",
        help = "The payment end-to-end UID"
    )
    private val payto by argument(
        help = "The credited account IBAN payto URI"
    ).convert { Payto.parse(it).expectIban() }

    override fun run() = cliCmd(logger) {
        nexusConfig(config).withDb { db, cfg ->
            val subject = requireNotNull(payto.message ?: subject) { "Missing subject" }
            val amount = requireNotNull(payto.amount ?: amount) { "Missing amount" }

            requireNotNull(payto.receiverName) { "Missing receiver name in creditor payto" }
            require(amount.currency == cfg.currency) {
                "Wrong currency: expected ${cfg.currency} got ${amount.currency}"
            }

            db.initiated.create(
                InitiatedPayment(
                    id = -1,
                    amount = amount,
                    subject = subject,
                    creditor = payto,
                    initiationTime = Instant.now(),
                    endToEndId = endToEndId ?: randEbicsId()
                )
            )
        }
    }
}