<?php
/**
 * Put the customers you already have onto your Listmonk list.
 *
 * The plugin subscribes people as they register or order; this is for the
 * ones who did so before you installed it. Copy this file into the root
 * of your site as backfill.php (it ships as a text file, so that a web server
 * never runs it where it is) and run it from a terminal:
 *
 *   php backfill.php                 # show what would happen, send nothing
 *   php backfill.php --run           # do it
 *   php backfill.php --run --limit=200
 *
 * It uses the plugin's own settings: the same instance, the same list, the
 * same consent rule. With the consent rule in force only customers whose
 * consent field says yes are included, which is the answer you want if
 * those addresses are going to receive marketing.
 *
 * Existing subscribers are left alone rather than overwritten, and the
 * list they are already on is never changed.
 *
 * @package	Hikashop Listmonk Plugin
 * @version	1.1.0
 * @author	HikaShop
 * @copyright	(C) 2010-2026 HIKARI SOFTWARE. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

// Command line only, checked before anything loads: a browser gets nothing.
if (PHP_SAPI !== 'cli') {
    http_response_code(403);
    exit("Run this from a terminal, not through the web server.\n");
}

const _JEXEC = 1;

define('JPATH_BASE', __DIR__);
require_once JPATH_BASE . '/includes/defines.php';
require_once JPATH_BASE . '/includes/framework.php';

$container = \Joomla\CMS\Factory::getContainer();
$container->alias('session', 'session.cli')
    ->alias('JSession', 'session.cli')
    ->alias(\Joomla\CMS\Session\Session::class, 'session.cli')
    ->alias(\Joomla\Session\Session::class, 'session.cli')
    ->alias(\Joomla\Session\SessionInterface::class, 'session.cli');

$app = $container->get(\Joomla\Console\Application::class);
\Joomla\CMS\Factory::$application = $app;

include_once JPATH_BASE . '/administrator/components/com_hikashop/helpers/helper.php';
require_once JPATH_PLUGINS . '/system/listmonk/listmonkApi.php';

$arguments = isset($argv) ? $argv : array();

$run = in_array('--run', $arguments, true);
$limit = 0;
foreach ($arguments as $arg) {
    if (strpos($arg, '--limit=') === 0) { $limit = (int) substr($arg, 8); }
}

// ── The plugin's settings ────────────────────────────────────────────

$descriptor = \Joomla\CMS\Plugin\PluginHelper::getPlugin('system', 'listmonk');
if (empty($descriptor)) {
    exit("The Listmonk plugin is not installed on this site.\n");
}
$params = new \Joomla\Registry\Registry($descriptor->params);

$url = (string) $params->get('url');
$listId = (int) $params->get('list_id');
if ($url === '' || $listId === 0) {
    exit("Configure the plugin first: its Listmonk address and the list to use.\n");
}

$api = new listmonkApi($url, (string) $params->get('api_user'),
    (string) $params->get('api_token'), (int) $params->get('timeout', 10));

$lists = $api->getLists();
if ($lists === false) {
    exit('Cannot reach Listmonk: ' . $api->lastError . "\n");
}
$listName = '';
$doubleOptin = false;
$found = (is_array($lists) && !empty($lists['results']) && is_array($lists['results'])) ? $lists['results'] : array();
foreach ($found as $l) {
    if ((int) $l['id'] === $listId) {
        $listName = $l['name'];
        $doubleOptin = (isset($l['optin']) && $l['optin'] === 'double');
    }
}
if ($listName === '') {
    exit("The list the plugin is configured with no longer exists on that Listmonk.\n");
}

// ── Who to send ──────────────────────────────────────────────────────

$db = \Joomla\CMS\Factory::getDbo();
$query = 'SELECT u.user_id, u.user_email, u.user_cms_id'
    . ' FROM ' . $db->quoteName('#__hikashop_user', 'u')
    . ' WHERE u.user_email <> ' . $db->quote('');

$mode = (string) $params->get('subscription_mode', 'consent_field');
// A field chosen earlier stays stored once the checkbox replaces it: it no longer counts.
$consentField = ((int) $params->get('consent_checkbox', 1) === 1) ? ''
    : preg_replace('/[^a-zA-Z0-9_]/', '', (string) $params->get('consent_field', ''));
if ($mode !== 'auto' && $consentField !== '') {
    $query .= ' AND u.' . $db->quoteName($consentField) . ' = '
        . $db->quote((string) $params->get('consent_required_value', '1'));
} elseif ($mode !== 'auto') {
    echo "Note: the plugin asks for consent through its own checkbox, which older\n"
        . "customers never saw. Nobody can be selected on that basis, so this only\n"
        . "makes sense with a consent field, or in 'every customer' mode.\n\n";
    exit(1);
}
// "Test on these addresses only" holds here as it does in the plugin.
$allow = trim((string) $params->get('test_allowlist', ''));
if ($allow !== '') {
    $query .= ' AND u.user_email LIKE ' . $db->quote('%' . $db->escape($allow, true) . '%', false);
}
$query .= ' ORDER BY u.user_id';
if ($limit > 0) { $query .= ' LIMIT ' . $limit; }

$db->setQuery($query);
$customers = $db->loadObjectList();
$total = count($customers);

echo 'Listmonk : ' . $url . "\n";
echo 'List     : ' . $listName . ($doubleOptin ? " (double opt-in: each one is asked to confirm)\n" : "\n");
echo 'Customers: ' . $total . ($mode === 'auto' ? ' (every customer)' : ' (with consent)') . "\n";
if ($allow !== '') {
    echo 'Test     : only addresses containing "' . $allow . "\", as set in the plugin\n";
}
echo $run ? "Mode     : sending\n\n" : "Mode     : dry run, nothing is sent\n\n";

// ── Send ─────────────────────────────────────────────────────────────

$added = $skipped = $failed = 0;
foreach ($customers as $customer) {
    $email = $customer->user_email;

    if (!$run) {
        $added++;
        if ($added <= 10) { echo '  would add ' . $email . "\n"; }
        continue;
    }

    $existing = $api->findSubscriber($email);
    if ($existing === false) {
        echo '  ERROR ' . $email . ' : ' . $api->lastError . "\n";
        $failed++;
        continue;
    }
    if ($existing !== null) {
        $skipped++;
        continue;
    }

    $name = '';
    if (!empty($customer->user_cms_id)) {
        $jUser = \Joomla\CMS\Factory::getUser((int) $customer->user_cms_id);
        if (!empty($jUser->name)) { $name = $jUser->name; }
    }

    $res = $api->createSubscriber($email, $name, $listId,
        array('source' => 'hikashop', 'backfilled' => gmdate('Y-m-d')), !$doubleOptin);
    if ($res === false) {
        echo '  ERROR ' . $email . ' : ' . $api->lastError . "\n";
        $failed++;
        continue;
    }
    $added++;
    if ($added % 100 === 0) { echo '  ' . $added . " added\n"; }
}

echo "\n";
if (!$run) {
    echo $added . " would be added. Run it again with --run to do it.\n";
    exit(0);
}
echo $added . ' added, ' . $skipped . ' already known, ' . $failed . " failed\n";
exit($failed === 0 ? 0 : 1);
