/** @odoo-module */
/* Copyright 2026 Criptomart - extracted from pos_payment_method_cashdro
   License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

   Adds refund (payout) support to the CashDro payment terminal integration.
   When the order due amount is negative (i.e. a return/refund), this module:
     1. Asks the cashier for the CashDro password to authorise the payout.
     2. Sends a type=3 (payout) request to the CashDro instead of the normal
        type=4 (collection) request.
     3. Sets the payment line amount to the negative amount dispensed by the
        machine (totalout).
   Normal (positive) payments are delegated unchanged to the original
   cashdro_send_payment_request method.
*/

import {PaymentCashdro} from "@pos_payment_method_cashdro/js/payment_cashdro.esm";
import {Gui} from "point_of_sale.Gui";
import {_t} from "web.core";

/**
 * Dedicated refund (payout) handler added to the CashDro prototype.
 *
 * Keeping this as a SEPARATE named method (rather than inlining it inside an
 * override of cashdro_send_payment_request) means that pos_cashdro_rounding
 * can always delegate refunds here regardless of which module loaded last.
 * Both modules patch cashdro_send_payment_request directly on the prototype,
 * so the last writer wins for that method; but _cashdro_send_refund_request is
 * only ever written by this module and is never overwritten.
 */
PaymentCashdro.prototype._cashdro_send_refund_request = async function (order) {
    const payment_line = order.selected_paymentline;
    const due = order.get_due(payment_line);
    // Include cash rounding if applied (same logic as pos_cashdro_rounding for
    // normal payments). get_rounding_applied() returns 0 when no rounding is
    // configured, so this is safe without pos_cashdro_rounding installed.
    const rounding = order.get_rounding_applied ? order.get_rounding_applied() : 0;
    const amount = Math.round(Math.abs(due + rounding) * 100);

    // Require password authorisation before opening the drawer for a payout.
    const {confirmed, payload: password} = await Gui.showPopup(
        "PasswordInputPopup",
        {
            title: _t("CashDro Refund Authorization"),
            body: _t("Enter the CashDro password to authorize this refund"),
            placeholder: _t("Password"),
        }
    );
    if (!confirmed) {
        payment_line.set_payment_status("retry");
        return false;
    }
    const method = payment_line.payment_method;
    if (password !== method.cashdro_password) {
        await Gui.showPopup("ErrorPopup", {
            title: _t("Authentication Failed"),
            body: _t("The CashDro password is incorrect."),
        });
        payment_line.set_payment_status("retry");
        return false;
    }

    const start_url = this._cashdro_payout_url({amount: amount});
    console.log(start_url);
    const res = await this._cashdro_request(start_url);
    console.log(res);
    const operation_id = res.data || "";
    this.pos.get_order().cashdro_operation = operation_id;

    const ack_url = this._cashdro_ack_url(operation_id);
    const res_ack = await this._cashdro_request(ack_url);
    console.log(res_ack);

    const ask_url = this._cashdro_ask_url(operation_id);
    const operation_data = await this._cashdro_request_payment(ask_url);
    console.log(operation_data);

    const data = JSON.parse(operation_data.data);
    payment_line.cashdro_operation_data = data;
    // CashDro reports the dispensed amount in totalout for payouts.
    // The API may return totalout as a negative value (money going out),
    // so we use Math.abs to get the magnitude and explicitly set the
    // payment line to a negative amount (refund to customer).
    const dispensed = Math.abs(data.operation.totalout) / 100;
    payment_line.set_amount(-dispensed);
    return true;
};

/**
 * Build the URL for a type=3 (payout/refund) operation on the CashDro.
 */
PaymentCashdro.prototype._cashdro_payout_url = function (parameters) {
    const user = this.pos.get_cashier().id || this.pos.user.id;
    let url = `${this._cashdro_url()}&operation=startOperation&type=3`;
    url += `&posid=pos-${this.pos.pos_session.name}`;
    url += `&posuser=${user}`;
    url += `&parameters=${encodeURIComponent(JSON.stringify(parameters))}`;
    return url;
};

/**
 * Override cashdro_send_payment_request to route refunds to
 * _cashdro_send_refund_request.
 *
 * NOTE: if pos_cashdro_rounding is also installed it will overwrite this
 * override (because "rounding" > "refund" alphabetically), but that is fine
 * because pos_cashdro_rounding also delegates negative amounts to
 * _cashdro_send_refund_request.  This override only matters when the rounding
 * module is NOT installed.
 */
const _originalSendPaymentRequest =
    PaymentCashdro.prototype.cashdro_send_payment_request;

PaymentCashdro.prototype.cashdro_send_payment_request = async function (order) {
    const payment_line = order.selected_paymentline;
    const due = order.get_due(payment_line);
    if (due < 0) {
        return this._cashdro_send_refund_request(order);
    }
    return _originalSendPaymentRequest.call(this, order);
};
