// Questo file fa parte di MyTown.
// MyTown è software libero: puoi ridistribuirlo e/o modificarlo secondo
// i termini della GNU Affero General Public License come pubblicata dalla
// Free Software Foundation, versione 3.
// Distribuito senza ALCUNA GARANZIA; vedi la GNU AGPL v3 per i dettagli.
// Copyright (C) Kondor Consulting & Services S.r.l.
// SPDX-License-Identifier: AGPL-3.0-or-later

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ConfigService } from './config.service';
import { ActivePaymentConfig, PaymentRequest, PayTransaction, PayType } from '../models/payment.model';

/**
 * Wrapper sul microservizio ws_spring_payment.
 * Endpoint allineati al portale Angular (portale_angular_18/pagamento/_services/pagamento.service.ts).
 * Riusa: PayType, PaymentRequest, PayTransaction, ActivePaymentConfig.
 */
@Injectable({ providedIn: 'root' })
export class PagamentoService {
	constructor(private http: HttpClient, private configService: ConfigService) {}

	/** GET /pay/types — lista tipi di pagamento attivi (NEXI, PAYPAL, CASH) */
	getPaymentTypes(): Observable<PayType[]> {
		return this.http
			.get<PayType[]>(`${this.configService.paymentUrl}pay/types`, { observe: 'response' })
			.pipe(map((r) => r.body as PayType[]));
	}

	/**
	 * POST /pay/config — genera la configurazione gateway (per CASH ritorna solo l'uid)
	 * e crea transazione PENDING.
	 * NOTA: responseType è text perché CASH ritorna una stringa nuda mentre NEXI/PAYPAL ritornano JSON.
	 */
	getPaymentConfig(req: PaymentRequest): Observable<string> {
		return this.http
			.post(`${this.configService.paymentUrl}pay/config`, req, { observe: 'response', responseType: 'text' })
			.pipe(map((r: any) => r.body as string));
	}

	/** POST /pay/save — salva lo stato finale della transazione (COMPLETED/FAILED/CANCELLED) */
	savePayment(req: PaymentRequest): Observable<any> {
		return this.http
			.post(`${this.configService.paymentUrl}pay/save`, req, { observe: 'response' })
			.pipe(map((r: any) => r.body));
	}

	/** POST /pay/refund — storno totale o parziale di una transazione COMPLETED */
	refundTransaction(uid: string, refundAmount?: number): Observable<any> {
		const body: any = { uid_transaction: uid };
		if (refundAmount && refundAmount > 0) body.refund_amount = refundAmount;
		return this.http
			.post(`${this.configService.paymentUrl}pay/refund`, body, { observe: 'response' })
			.pipe(map((r: any) => r.body));
	}

	/** POST /pay/reconcile — riconciliazione manuale di una transazione PENDING */
	reconcileTransaction(uid: string): Observable<any> {
		return this.http
			.post(`${this.configService.paymentUrl}pay/reconcile`, { uid_transaction: uid }, { observe: 'response' })
			.pipe(map((r: any) => r.body));
	}

	/** POST /pay/link-pp-order — associa al record PENDING l'order id PayPal */
	linkPayPalOrder(uid: string, externalId: string): Observable<any> {
		return this.http
			.post(`${this.configService.paymentUrl}pay/link-pp-order`, {
				uid_transaction: uid,
				external_id: externalId,
			}, { observe: 'response' })
			.pipe(map((r: any) => r.body));
	}

	/** GET /company-config/active-by-company/{cmp_id} — config ATTIVE per un'azienda (no credenziali) */
	getActiveConfigsByCompany(cmpId: number): Observable<ActivePaymentConfig[]> {
		return this.http
			.get<ActivePaymentConfig[]>(`${this.configService.paymentUrl}company-config/active-by-company/${cmpId}`, { observe: 'response' })
			.pipe(map((r) => r.body as ActivePaymentConfig[]));
	}

	/** GET /pay/transactions/{module}/{entity_id} — storico transazioni per entità */
	getTransactions(module: string, entityId: number): Observable<PayTransaction[]> {
		return this.http
			.get<PayTransaction[]>(`${this.configService.paymentUrl}pay/transactions/${module}/${entityId}`, { observe: 'response' })
			.pipe(map((r) => r.body as PayTransaction[]));
	}
}
