<?php
/**
 * WP-CLI Commands for LangForge
 *
 * @package LangForge
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

if (!defined('WP_CLI') || !WP_CLI) {
    return;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- LF_ is the established plugin class prefix
class LF_CLI extends WP_CLI_Command {

    /**
 * Show translation status overview.
 *
 * ## EXAMPLES
 * wp langforge status
 *
 * @subcommand status
 */
    public function status($args, $assoc_args) {
        $languages = LF_Core::instance()->get_active_languages();
        $default_lang = LF_Core::instance()->get_default_language();
        $translatable = LF_Core::get_translatable_post_types();

        global $wpdb;

        $rows = [];
        foreach ($languages as $code => $lang) {
            $count = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- own table from $wpdb->prefix; one-time/admin read
                "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p
                INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
                WHERE p.post_status = 'publish' AND pm.meta_key = '_lf_language' AND pm.meta_value = %s",
                $code
            ));

            $rows[] = [
                'Code' => $code,
                'Language' => $lang['native_name'],
                'Posts' => (int) $count,
                'Default' => $code === $default_lang ? 'Yes' : '',
            ];
        }

        WP_CLI\Utils\format_items('table', $rows, ['Code', 'Language', 'Posts', 'Default']);
    }

    /**
 * List active languages.
 *
 * ## EXAMPLES
 * wp langforge languages
 *
 * @subcommand languages
 */
    public function languages($args, $assoc_args) {
        $languages = LF_Core::instance()->get_active_languages();
        $default = LF_Core::instance()->get_default_language();

        $rows = [];
        foreach ($languages as $code => $lang) {
            $rows[] = [
                'Code' => $code,
                'Name' => $lang['name'],
                'Native' => $lang['native_name'],
                'Locale' => $lang['locale'],
                'Default' => $code === $default ? '*' : '',
            ];
        }

        WP_CLI\Utils\format_items('table', $rows, ['Code', 'Name', 'Native', 'Locale', 'Default']);
    }

    /**
 * Create a translation for a post.
 *
 * ## OPTIONS
 * <post_id>
 * : Source post ID.
 *
 * <language>
 * : Target language code.
 *
 * ## EXAMPLES
 * wp langforge translate 42 en
 *
 * @subcommand translate
 */
    public function translate($args, $assoc_args) {
        list($post_id, $language) = $args;
        $post_id = (int) $post_id;

        $post = get_post($post_id);
        if (!$post) {
            WP_CLI::error("Post $post_id not found.");
        }

        $existing = LF_Post_Translation::instance()->get_translation($post_id, $language);
        if ($existing) {
            WP_CLI::warning("Translation already exists: post #$existing");
            return;
        }

        $new_id = wp_insert_post([
            'post_title' => $post->post_title,
            'post_content' => $post->post_content,
            'post_excerpt' => $post->post_excerpt,
            'post_status' => 'draft',
            'post_type' => $post->post_type,
            'post_name' => $post->post_name,
        ]);

        if (is_wp_error($new_id)) {
            WP_CLI::error($new_id->get_error_message());
        }

        LF_Post_Translation::instance()->set_post_language($new_id, $language);
        LF_Post_Translation::instance()->link_translations($post_id, $new_id);

        // v9: synchronous LearnDash relationship-meta write.
        // The mapper lives in langforge-pro; on Free-only sites this is a no-op
        // (LearnDash integration is a Pro feature).
        if (class_exists('LF_LearnDash_Mapper') && LF_LearnDash_Mapper::is_learndash_active()) {
            LF_LearnDash_Mapper::apply($post_id, $new_id, $language);
        }

        do_action('lf_translation_created', $post_id, $new_id, $language); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- intentional ACF/WPML/core compatibility

        WP_CLI::success("Created translation #$new_id ($language) for post #$post_id.");
    }

    /**
 * Set language for a post.
 *
 * ## OPTIONS
 * <post_id>
 * : Post ID.
 *
 * <language>
 * : Language code.
 *
 * ## EXAMPLES
 * wp langforge set-language 42 ru
 *
 * @subcommand set-language
 */
    public function set_language($args, $assoc_args) {
        list($post_id, $language) = $args;

        if (!get_post($post_id)) {
            WP_CLI::error("Post $post_id not found.");
        }

        LF_Post_Translation::instance()->set_post_language((int) $post_id, $language);
        WP_CLI::success("Set language '$language' for post #$post_id.");
    }

    /**
 * Link two posts as translations of each other.
 *
 * ## OPTIONS
 * <post_id_1>
 * <post_id_2>
 *
 * ## EXAMPLES
 * wp langforge link 42 99
 *
 * @subcommand link
 */
    public function link($args, $assoc_args) {
        list($id1, $id2) = $args;
        LF_Post_Translation::instance()->link_translations((int) $id1, (int) $id2);
        WP_CLI::success("Linked posts #$id1 and #$id2 as translations.");
    }

    /**
 * Unlink a translation.
 *
 * ## OPTIONS
 * <post_id>
 * <language>
 *
 * ## EXAMPLES
 * wp langforge unlink 42 en
 *
 * @subcommand unlink
 */
    public function unlink($args, $assoc_args) {
        list($post_id, $language) = $args;
        LF_Post_Translation::instance()->unlink_translation((int) $post_id, $language);
        WP_CLI::success("Unlinked $language translation from post #$post_id.");
    }

    /**
 * Populate Translation Memory from existing translations.
 *
 * ## EXAMPLES
 * wp langforge tm-populate
 *
 * @subcommand tm-populate
 */
    public function tm_populate($args, $assoc_args) {
        if (!class_exists('LF_Translation_Memory')) {
            WP_CLI::error('Translation Memory requires the Lang Forge Pro add-on.');
        }
        WP_CLI::log('Populating Translation Memory from existing translations...');
        $count = LF_Translation_Memory::instance()->bulk_populate();
        WP_CLI::success("Added $count segments to Translation Memory.");
    }

    /**
 * Export translations.
 *
 * ## OPTIONS
 * --lang=<language>
 * : Target language code.
 *
 * [--format=<format>]
 * : Export format (xliff or csv). Default: xliff.
 *
 * [--output=<file>]
 * : Output file path.
 *
 * ## EXAMPLES
 * wp langforge export --lang=en --format=xliff --output=export.xliff
 *
 * @subcommand export
 */
    public function export($args, $assoc_args) {
        $target = $assoc_args['lang'] ?? '';
        $format = $assoc_args['format'] ?? 'xliff';
        $output = $assoc_args['output'] ?? '';
        $source = LF_Core::instance()->get_default_language();

        if (!$target) {
            WP_CLI::error('--lang is required.');
        }

        if (!class_exists('LF_Import_Export')) {
            WP_CLI::error('Import / Export requires the Lang Forge Pro add-on.');
        }
        $exporter = LF_Import_Export::instance();

        if ($format === 'csv') {
            $content = $exporter->export_csv($source, $target);
            $ext = 'csv';
        } else {
            $content = $exporter->export_xliff($source, $target);
            $ext = 'xliff';
        }

        if (!$output) {
            $output = "langforge-export-{$source}-{$target}.{$ext}";
        }

        file_put_contents($output, $content);
        WP_CLI::success("Exported to $output");
    }

    /**
 * Import translations from file.
 *
 * ## OPTIONS
 * <file>
 * : Path to XLIFF or CSV file.
 *
 * ## EXAMPLES
 * wp langforge import translations.xliff
 *
 * @subcommand import
 */
    public function import($args, $assoc_args) {
        $file = $args[0];
        if (!file_exists($file)) {
            WP_CLI::error("File not found: $file");
        }

        if (!class_exists('LF_Import_Export')) {
            WP_CLI::error('Import / Export requires the Lang Forge Pro add-on.');
        }
        $content = file_get_contents($file);
        $ext = pathinfo($file, PATHINFO_EXTENSION);
        $importer = LF_Import_Export::instance();

        if (in_array($ext, ['xliff', 'xlf'])) {
            $result = $importer->import_xliff($content);
        } elseif ($ext === 'csv') {
            $result = $importer->import_csv($content);
        } else {
            WP_CLI::error("Unsupported format: $ext. Use .xliff or .csv");
        }

        if ($result['success']) {
            WP_CLI::success("Imported {$result['imported']} translations.");
        } else {
            WP_CLI::error($result['error'] ?? 'Import failed.');
        }
    }

    /**
 * Flush rewrite rules.
 *
 * ## EXAMPLES
 * wp langforge flush
 *
 * @subcommand flush
 */
    public function flush($args, $assoc_args) {
        flush_rewrite_rules();
        WP_CLI::success('Rewrite rules flushed.');
    }
}
