<?php
/* Copyright (C) 2026  Eduard Wisch  <data@data-it-solution.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 */

/**
 * \file    bankimport/confirm.php
 * \ingroup bankimport
 * \brief   Payment confirmation page - match bank transactions to invoices
 */

// Load Dolibarr environment
$res = 0;
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
	$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
}
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
$tmp2 = realpath(__FILE__);
$i = strlen($tmp) - 1;
$j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
	$i--;
	$j--;
}
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
	$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
}
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
	$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
}
if (!$res && file_exists("../main.inc.php")) {
	$res = @include "../main.inc.php";
}
if (!$res && file_exists("../../main.inc.php")) {
	$res = @include "../../main.inc.php";
}
if (!$res) {
	die("Include of main fails");
}

require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
dol_include_once('/bankimport/class/banktransaction.class.php');
dol_include_once('/bankimport/lib/bankimport.lib.php');

/**
 * @var Conf $conf
 * @var DoliDB $db
 * @var Translate $langs
 * @var User $user
 */

$langs->loadLangs(array("bankimport@bankimport", "banks", "bills"));

$action = GETPOST('action', 'aZ09');

// Security check
if (!$user->hasRight('bankimport', 'write')) {
	accessforbidden();
}

$bankAccountId = getDolGlobalInt('BANKIMPORT_BANK_ACCOUNT_ID');

/*
 * Actions
 */

// Confirm single payment
if ($action == 'confirmpayment' && !empty($bankAccountId)) {
	$transid = GETPOSTINT('transid');
	$matchtype = GETPOST('matchtype', 'alpha');
	$matchid = GETPOSTINT('matchid');

	if ($transid > 0 && !empty($matchtype) && $matchid > 0) {
		$trans = new BankImportTransaction($db);
		if ($trans->fetch($transid) > 0) {
			if ($trans->status != BankImportTransaction::STATUS_NEW) {
				setEventMessages($langs->trans("TransactionAlreadyProcessed"), null, 'warnings');
			} else {
				$result = $trans->confirmPayment($user, $matchtype, $matchid, $bankAccountId);
				if ($result > 0) {
					setEventMessages($langs->trans("PaymentCreatedSuccessfully", dol_escape_htmltag($trans->name), price(abs($trans->amount))), null, 'mesgs');
				} else {
					setEventMessages($trans->error, $trans->errors, 'errors');
				}
			}
		}
	}

	header("Location: ".$_SERVER["PHP_SELF"]."?token=".newToken());
	exit;
}

// Confirm multiple invoices payment
if ($action == 'confirmmulti' && !empty($bankAccountId)) {
	$transid = GETPOSTINT('transid');
	$invoiceIds = GETPOST('invoices', 'array');

	if ($transid > 0 && !empty($invoiceIds)) {
		$trans = new BankImportTransaction($db);
		if ($trans->fetch($transid) > 0) {
			if ($trans->status != BankImportTransaction::STATUS_NEW) {
				setEventMessages($langs->trans("TransactionAlreadyProcessed"), null, 'warnings');
			} else {
				// Build invoices array with amounts
				require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
				$invoices = array();
				foreach ($invoiceIds as $invId) {
					$invId = (int) $invId;
					if ($invId > 0) {
						$invoice = new FactureFournisseur($db);
						if ($invoice->fetch($invId) > 0) {
							$alreadyPaid = $invoice->getSommePaiement();
							$creditnotes = $invoice->getSumCreditNotesUsed();
							$deposits = $invoice->getSumDepositsUsed();
							$remainToPay = price2num($invoice->total_ttc - $alreadyPaid - $creditnotes - $deposits, 'MT');
							if ($remainToPay > 0) {
								$invoices[] = array(
									'type' => 'facture_fourn',
									'id' => $invId,
									'ref' => $invoice->ref,
									'amount' => $remainToPay
								);
							}
						}
					}
				}

				if (!empty($invoices)) {
					$result = $trans->confirmMultiplePayment($user, $invoices, $bankAccountId);
					if ($result > 0) {
						setEventMessages($langs->trans("PaymentCreatedSuccessfully", dol_escape_htmltag($trans->name), price(abs($trans->amount))).' ('.count($invoices).' '.$langs->trans("Invoices").')', null, 'mesgs');
					} else {
						setEventMessages($trans->error, $trans->errors, 'errors');
					}
				} else {
					setEventMessages($langs->trans("NoInvoicesSelected"), null, 'errors');
				}
			}
		}
	}

	header("Location: ".$_SERVER["PHP_SELF"]."?token=".newToken());
	exit;
}

// Confirm all high-score matches
if ($action == 'confirmall' && !empty($bankAccountId)) {
	$transaction = new BankImportTransaction($db);
	$transactions = $transaction->fetchAll('date_trans', 'DESC', 0, 0, array('status' => BankImportTransaction::STATUS_NEW));

	$created = 0;
	$failed = 0;

	if (is_array($transactions)) {
		foreach ($transactions as $trans) {
			$matches = $trans->findMatches();
			if (!empty($matches) && $matches[0]['match_score'] >= 80) {
				$bestMatch = $matches[0];

				// Handle multi-invoice matches
				if ($bestMatch['type'] == 'multi_facture_fourn' && !empty($bestMatch['invoices'])) {
					$invoices = array();
					foreach ($bestMatch['invoices'] as $inv) {
						$invoices[] = array(
							'type' => 'facture_fourn',
							'id' => $inv['id'],
							'ref' => $inv['ref'],
							'amount' => $inv['amount']
						);
					}
					$result = $trans->confirmMultiplePayment($user, $invoices, $bankAccountId);
				} else {
					$result = $trans->confirmPayment($user, $bestMatch['type'], $bestMatch['id'], $bankAccountId);
				}

				if ($result > 0) {
					$created++;
				} else {
					$failed++;
				}
			}
		}
	}

	if ($created > 0 || $failed > 0) {
		setEventMessages($langs->trans("PaymentsCreatedSummary", $created, $failed), null, $failed > 0 ? 'warnings' : 'mesgs');
	} else {
		setEventMessages($langs->trans("NoNewMatchesFound"), null, 'warnings');
	}

	header("Location: ".$_SERVER["PHP_SELF"]."?token=".newToken());
	exit;
}

// Ignore transaction
if ($action == 'ignore') {
	$transid = GETPOSTINT('transid');
	if ($transid > 0) {
		$trans = new BankImportTransaction($db);
		if ($trans->fetch($transid) > 0 && $trans->status == BankImportTransaction::STATUS_NEW) {
			$trans->setStatus(BankImportTransaction::STATUS_IGNORED, $user);
			setEventMessages($langs->trans("StatusUpdated"), null, 'mesgs');
		}
	}
	header("Location: ".$_SERVER["PHP_SELF"]."?token=".newToken());
	exit;
}


/*
 * View
 */

$form = new Form($db);

$title = $langs->trans("PaymentConfirmation");
llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-bankimport page-confirm');

print load_fiche_titre($title, '', 'bank');

// Check if bank account is configured
if (empty($bankAccountId)) {
	print '<div class="warning">';
	print img_warning().' '.$langs->trans("ErrorNoBankAccountConfigured");
	print ' <a href="'.dol_buildpath('/bankimport/admin/setup.php', 1).'">'.$langs->trans("GoToSetup").'</a>';
	print '</div>';
	llxFooter();
	$db->close();
	exit;
}

// Description
print '<div class="opacitymedium" style="margin-bottom: 15px;">'.$langs->trans("PaymentConfirmationDesc").'</div>';

// Fetch all new transactions and find matches
$transaction = new BankImportTransaction($db);
$transactions = $transaction->fetchAll('date_trans', 'DESC', 0, 0, array('status' => BankImportTransaction::STATUS_NEW));

$pendingMatches = array(); // transactions with matches
$noMatches = array();      // transactions without matches

if (is_array($transactions)) {
	foreach ($transactions as $trans) {
		$matches = $trans->findMatches();
		if (!empty($matches)) {
			$pendingMatches[] = array('transaction' => $trans, 'matches' => $matches);
		} else {
			$noMatches[] = $trans;
		}
	}
}

// Confirm all button (if high-score matches exist)
$highScoreCount = 0;
foreach ($pendingMatches as $pm) {
	if ($pm['matches'][0]['match_score'] >= 80) {
		$highScoreCount++;
	}
}

if ($highScoreCount > 0) {
	print '<div class="tabsAction">';
	print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=confirmall&token='.newToken().'">';
	print $langs->trans("ConfirmAllHighScore").' ('.$highScoreCount.')';
	print '</a>';
	print '</div>';
}

// Match reasons translation
$reasonLabels = array(
	'ref' => $langs->trans("MatchByRef"),
	'ref_client' => $langs->trans("MatchByClientRef"),
	'ref_supplier' => $langs->trans("MatchBySupplierRef"),
	'amount' => $langs->trans("MatchByAmount"),
	'amount_close' => $langs->trans("MatchByAmountClose"),
	'name_exact' => $langs->trans("MatchByNameExact"),
	'name_similar' => $langs->trans("MatchByNameSimilar"),
	'iban' => $langs->trans("MatchByIBAN"),
	'multi_invoice' => $langs->trans("MatchByMultiInvoice")
);

if (!empty($pendingMatches)) {
	print '<div class="div-table-responsive">';
	print '<table class="noborder centpercent">';
	print '<tr class="liste_titre">';
	print '<th>'.$langs->trans("Date").'</th>';
	print '<th>'.$langs->trans("Counterparty").'</th>';
	print '<th class="right">'.$langs->trans("Amount").' ('.$langs->trans("Transaction").')</th>';
	print '<th style="text-align: center; width: 30px;"></th>';
	print '<th>'.$langs->trans("Invoice").'</th>';
	print '<th>'.$langs->trans("ThirdParty").'</th>';
	print '<th class="right">'.$langs->trans("Amount").' ('.$langs->trans("Invoice").')</th>';
	print '<th class="center">'.$langs->trans("Score").'</th>';
	print '<th>'.$langs->trans("MatchReason").'</th>';
	print '<th class="center">'.$langs->trans("Action").'</th>';
	print '</tr>';

	foreach ($pendingMatches as $pm) {
		$trans = $pm['transaction'];
		$bestMatch = $pm['matches'][0];
		$isMultiInvoice = ($bestMatch['type'] == 'multi_facture_fourn');

		// Score color
		$scoreColor = $bestMatch['match_score'] >= 80 ? '#4caf50' : ($bestMatch['match_score'] >= 60 ? '#ff9800' : '#9e9e9e');

		print '<tr class="oddeven">';

		// Transaction date
		print '<td class="nowraponall">'.dol_print_date($trans->date_trans, 'day').'</td>';

		// Counterparty name + description
		print '<td class="tdoverflowmax200">';
		print '<a href="'.dol_buildpath('/bankimport/card.php', 1).'?id='.$trans->id.'">'.dol_escape_htmltag(dol_trunc($trans->name, 30)).'</a>';
		if ($trans->description) {
			print '<br><span class="opacitymedium small">'.dol_escape_htmltag(dol_trunc($trans->description, 50)).'</span>';
		}
		print '</td>';

		// Transaction amount
		print '<td class="right nowraponall">';
		if ($trans->amount >= 0) {
			print '<span style="color: green; font-weight: bold;">+'.price($trans->amount, 0, $langs, 1, -1, 2, $trans->currency).'</span>';
		} else {
			print '<span style="color: red; font-weight: bold;">'.price($trans->amount, 0, $langs, 1, -1, 2, $trans->currency).'</span>';
		}
		print '</td>';

		// Arrow
		print '<td class="center" style="font-size: 1.3em;">&harr;</td>';

		// Invoice reference(s)
		print '<td class="nowraponall">';
		if ($isMultiInvoice && !empty($bestMatch['invoices'])) {
			// Multi-invoice display
			require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
			print '<strong>'.count($bestMatch['invoices']).' '.$langs->trans("Invoices").':</strong><br>';
			foreach ($bestMatch['invoices'] as $invData) {
				$inv = new FactureFournisseur($db);
				$inv->fetch($invData['id']);
				print $inv->getNomUrl(1).' <span class="opacitymedium small">('.price($invData['amount'], 0, $langs, 1, -1, 2, 'EUR').')</span><br>';
			}
		} elseif ($bestMatch['type'] == 'facture') {
			require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
			$inv = new Facture($db);
			$inv->fetch($bestMatch['id']);
			print $inv->getNomUrl(1);
		} else {
			require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
			$inv = new FactureFournisseur($db);
			$inv->fetch($bestMatch['id']);
			print $inv->getNomUrl(1);
		}
		print '</td>';

		// Third party
		print '<td class="tdoverflowmax150">';
		if ($bestMatch['socid'] > 0) {
			require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
			$soc = new Societe($db);
			$soc->fetch($bestMatch['socid']);
			print $soc->getNomUrl(1);
		} else {
			print dol_escape_htmltag($bestMatch['socname']);
		}
		print '</td>';

		// Invoice amount
		print '<td class="right nowraponall">';
		print price($bestMatch['amount'], 0, $langs, 1, -1, 2, 'EUR');
		if ($isMultiInvoice && isset($bestMatch['difference']) && abs($bestMatch['difference']) > 0.01) {
			$diffColor = $bestMatch['difference'] > 0 ? 'orange' : 'green';
			print '<br><span class="small" style="color: '.$diffColor.';">'.($bestMatch['difference'] > 0 ? '+' : '').price($bestMatch['difference'], 0, $langs, 1, -1, 2, 'EUR').'</span>';
		}
		print '</td>';

		// Score
		print '<td class="center"><span style="color: '.$scoreColor.'; font-weight: bold; font-size: 1.1em;">'.$bestMatch['match_score'].'%</span></td>';

		// Match reasons
		print '<td>';
		if (!empty($bestMatch['match_reasons'])) {
			foreach ($bestMatch['match_reasons'] as $reason) {
				$label = $reasonLabels[$reason] ?? $reason;
				print '<span class="badge badge-secondary">'.$label.'</span> ';
			}
		}
		print '</td>';

		// Actions
		print '<td class="center nowraponall">';

		if ($isMultiInvoice && !empty($bestMatch['invoices'])) {
			// Multi-invoice: Form with checkboxes for selection
			print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
			print '<input type="hidden" name="token" value="'.newToken().'">';
			print '<input type="hidden" name="action" value="confirmmulti">';
			print '<input type="hidden" name="transid" value="'.$trans->id.'">';

			print '<div style="text-align: left; margin-bottom: 5px;">';
			foreach ($bestMatch['invoices'] as $invData) {
				print '<label style="display: block; margin: 2px 0;">';
				print '<input type="checkbox" name="invoices[]" value="'.$invData['id'].'" checked> ';
				print dol_escape_htmltag($invData['ref_supplier'] ?: $invData['ref']).' ('.price($invData['amount'], 0, $langs, 1, -1, 2, 'EUR').')';
				print '</label>';
			}
			print '</div>';

			print '<button type="submit" class="butActionSmall">'.$langs->trans("ConfirmPayment").'</button>';
			print '</form>';
		} else {
			// Single invoice: Confirm payment button
			print '<a class="butActionSmall" href="'.$_SERVER["PHP_SELF"].'?action=confirmpayment&transid='.$trans->id.'&matchtype='.urlencode($bestMatch['type']).'&matchid='.$bestMatch['id'].'&token='.newToken().'">';
			print $langs->trans("ConfirmPayment");
			print '</a>';
		}

		print '<br>';
		// Ignore button
		print '<a class="butActionSmall button-cancel" style="margin-top: 3px;" href="'.$_SERVER["PHP_SELF"].'?action=ignore&transid='.$trans->id.'&token='.newToken().'">';
		print $langs->trans("SetAsIgnored");
		print '</a>';

		// Show alternatives if multiple matches
		if (count($pm['matches']) > 1) {
			print '<br><a class="small opacitymedium" style="margin-top: 3px;" href="'.dol_buildpath('/bankimport/card.php', 1).'?id='.$trans->id.'&action=findmatches&token='.newToken().'">';
			print '+'.($count = count($pm['matches']) - 1).' '.$langs->trans("Alternatives");
			print '</a>';
		}
		print '</td>';

		print '</tr>';
	}

	print '</table>';
	print '</div>';
} else {
	print '<div class="opacitymedium" style="padding: 20px; text-align: center;">';
	print $langs->trans("NoNewMatchesFound");
	print '</div>';
}

// Show unmatched transactions count
if (!empty($noMatches)) {
	print '<br>';
	print '<div class="info">';
	print img_picto('', 'info', 'class="pictofixedwidth"');
	print $langs->trans("UnmatchedTransactions", count($noMatches));
	print ' <a href="'.dol_buildpath('/bankimport/list.php', 1).'?search_status=0">'.$langs->trans("ShowAll").'</a>';
	print '</div>';
}

llxFooter();
$db->close();
