<?php
/**
 * Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * One-time migration from MokoCassiopeia → MokoOnyx.
 * Called from index.php on first page load. Creates a .migrated
 * marker file so it only runs once.
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Log\Log;

(function () {
    $markerFile = __DIR__ . '/../.migrated';

    // Already migrated
    if (file_exists($markerFile)) {
        return;
    }

    $db  = Factory::getDbo();
    $app = Factory::getApplication();

    $oldName    = 'mokocassiopeia';
    $newName    = 'mokoonyx';
    $oldDisplay = 'MokoCassiopeia';
    $newDisplay = 'MokoOnyx';

    // Init logger
    Log::addLogger(
        ['text_file' => 'mokoonyx_migrate.log.php'],
        Log::ALL,
        ['mokoonyx_migrate']
    );

    $log = function (string $msg, int $level = Log::INFO) {
        Log::add($msg, $level, 'mokoonyx_migrate');
    };

    $log('=== MokoOnyx migration started (index.php bootstrap) ===');

    // Check if MokoCassiopeia has styles to migrate
    $query = $db->getQuery(true)
        ->select('*')
        ->from('#__template_styles')
        ->where($db->quoteName('template') . ' = ' . $db->quote($oldName))
        ->where($db->quoteName('client_id') . ' = 0');
    $oldStyles = $db->setQuery($query)->loadObjectList();

    if (empty($oldStyles)) {
        $log('No MokoCassiopeia styles found — fresh install, nothing to migrate.');
        @file_put_contents($markerFile, date('Y-m-d H:i:s') . ' fresh install');
        return;
    }

    $log('Found ' . count($oldStyles) . ' MokoCassiopeia style(s) to migrate.');

    // Get the default MokoOnyx style (created by Joomla installer)
    $query = $db->getQuery(true)
        ->select('id')
        ->from('#__template_styles')
        ->where($db->quoteName('template') . ' = ' . $db->quote($newName))
        ->where($db->quoteName('client_id') . ' = 0')
        ->order($db->quoteName('id') . ' ASC');
    $defaultOnyxId = (int) $db->setQuery($query, 0, 1)->loadResult();

    $isFirst = true;

    foreach ($oldStyles as $old) {
        $newTitle  = str_replace($oldDisplay, $newDisplay, $old->title);
        $newTitle  = str_replace($oldName, $newName, $newTitle);
        $newParams = is_string($old->params)
            ? str_replace($oldName, $newName, $old->params)
            : $old->params;

        if ($isFirst && $defaultOnyxId) {
            // Apply params to the installer-created default MokoOnyx style
            $update = $db->getQuery(true)
                ->update('#__template_styles')
                ->set($db->quoteName('title')  . ' = ' . $db->quote($newTitle))
                ->set($db->quoteName('params') . ' = ' . $db->quote($newParams))
                ->where('id = ' . $defaultOnyxId);
            $db->setQuery($update)->execute();

            // Set as default if MokoCassiopeia was default
            if ($old->home == 1) {
                $db->setQuery(
                    $db->getQuery(true)
                        ->update('#__template_styles')
                        ->set($db->quoteName('home') . ' = 1')
                        ->where('id = ' . $defaultOnyxId)
                )->execute();

                $db->setQuery(
                    $db->getQuery(true)
                        ->update('#__template_styles')
                        ->set($db->quoteName('home') . ' = 0')
                        ->where('id = ' . (int) $old->id)
                )->execute();

                $log('Set MokoOnyx as default site template.');
            }

            $log("Applied params to default MokoOnyx style: {$newTitle}");
            $isFirst = false;
            continue;
        }

        // Additional styles: check if already exists
        $check = $db->getQuery(true)
            ->select('COUNT(*)')
            ->from('#__template_styles')
            ->where($db->quoteName('template') . ' = ' . $db->quote($newName))
            ->where($db->quoteName('title') . ' = ' . $db->quote($newTitle));
        if ((int) $db->setQuery($check)->loadResult() > 0) {
            $log("Style '{$newTitle}' already exists — skipping.");
            continue;
        }

        // Create new MokoOnyx style copy
        $new = clone $old;
        unset($new->id);
        $new->template = $newName;
        $new->title    = $newTitle;
        $new->params   = $newParams;
        $new->home     = 0;

        try {
            $db->insertObject('#__template_styles', $new, 'id');
            $log("Created MokoOnyx style: {$newTitle}");
        } catch (\Throwable $e) {
            $log("Failed to create style '{$newTitle}': " . $e->getMessage(), Log::WARNING);
        }
    }

    // Copy user files from MokoCassiopeia media
    $oldMedia = JPATH_ROOT . '/media/templates/site/' . $oldName;
    $newMedia = JPATH_ROOT . '/media/templates/site/' . $newName;

    if (is_dir($oldMedia) && is_dir($newMedia)) {
        $userFiles = [
            'css/theme/light.custom.css',
            'css/theme/dark.custom.css',
            'css/theme/light.custom.min.css',
            'css/theme/dark.custom.min.css',
            'css/user.css',
            'css/user.min.css',
            'js/user.js',
            'js/user.min.js',
        ];

        $copied = 0;
        foreach ($userFiles as $rel) {
            $src = $oldMedia . '/' . $rel;
            $dst = $newMedia . '/' . $rel;
            if (is_file($src) && !is_file($dst)) {
                $dir = dirname($dst);
                if (!is_dir($dir)) {
                    mkdir($dir, 0755, true);
                }
                copy($src, $dst);
                $copied++;
            }
        }

        if ($copied > 0) {
            $log("Copied {$copied} user file(s) from MokoCassiopeia.");
        }
    }

    // Replace MokoCassiopeia references in article content
    try {
        $contentTables = [
            ['table' => '#__content', 'columns' => ['introtext', 'fulltext']],
        ];

        $totalReplaced = 0;

        foreach ($contentTables as $spec) {
            foreach ($spec['columns'] as $col) {
                $query = $db->getQuery(true)
                    ->update($spec['table'])
                    ->set(
                        $db->quoteName($col) . ' = REPLACE(REPLACE('
                        . $db->quoteName($col) . ', '
                        . $db->quote($oldDisplay) . ', '
                        . $db->quote($newDisplay) . '), '
                        . $db->quote($oldName) . ', '
                        . $db->quote($newName) . ')'
                    )
                    ->where(
                        '(' . $db->quoteName($col) . ' LIKE ' . $db->quote('%' . $oldDisplay . '%')
                        . ' OR ' . $db->quoteName($col) . ' LIKE ' . $db->quote('%' . $oldName . '%') . ')'
                    );
                $db->setQuery($query)->execute();
                $totalReplaced += $db->getAffectedRows();
            }
        }

        if ($totalReplaced > 0) {
            $log("Replaced MokoCassiopeia references in {$totalReplaced} content row(s).");
        }
    } catch (\Throwable $e) {
        $log('Content replacement failed: ' . $e->getMessage(), Log::WARNING);
    }

    // Replace MokoCassiopeia references in custom HTML modules
    try {
        $query = $db->getQuery(true)
            ->update('#__modules')
            ->set(
                $db->quoteName('content') . ' = REPLACE(REPLACE('
                . $db->quoteName('content') . ', '
                . $db->quote($oldDisplay) . ', '
                . $db->quote($newDisplay) . '), '
                . $db->quote($oldName) . ', '
                . $db->quote($newName) . ')'
            )
            ->where(
                '(' . $db->quoteName('content') . ' LIKE ' . $db->quote('%' . $oldDisplay . '%')
                . ' OR ' . $db->quoteName('content') . ' LIKE ' . $db->quote('%' . $oldName . '%') . ')'
            );
        $db->setQuery($query)->execute();
        $modulesUpdated = $db->getAffectedRows();

        if ($modulesUpdated > 0) {
            $log("Replaced MokoCassiopeia references in {$modulesUpdated} module(s).");
        }
    } catch (\Throwable $e) {
        $log('Module content replacement failed: ' . $e->getMessage(), Log::WARNING);
    }

    // Update the update server
    try {
        $onyxUpdatesUrl = 'https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/updates.xml';
        $query = $db->getQuery(true)
            ->update('#__update_sites')
            ->set($db->quoteName('location') . ' = ' . $db->quote($onyxUpdatesUrl))
            ->set($db->quoteName('name') . ' = ' . $db->quote($newDisplay))
            ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%MokoCassiopeia%'));
        $db->setQuery($query)->execute();
        $n = $db->getAffectedRows();
        if ($n > 0) {
            $log("Redirected {$n} update site(s) to MokoOnyx.");
        }
    } catch (\Throwable $e) {
        $log('Update server redirect failed: ' . $e->getMessage(), Log::WARNING);
    }

    // Write marker file
    @file_put_contents($markerFile, date('Y-m-d H:i:s') . " migrated {$oldName} → {$newName}");

    $log('=== Migration completed ===');

    // Enqueue message for admin
    if ($app->isClient('administrator')) {
        $app->enqueueMessage(
            '<strong>MokoOnyx has imported your MokoCassiopeia settings.</strong><br>'
            . 'You can safely uninstall MokoCassiopeia from Extensions &rarr; Manage.',
            'success'
        );
    }
})();
