<?php
if (!defined('ABSPATH')) exit;

define('WEBABILITY_THEME_FIXES_KEY', 'webability_theme_fixes');
define('WEBABILITY_FIX_BACKUP_KEY', 'webability_fix_backups');

/**
 * AJAX: Apply a single fix by index.
 */
add_action('wp_ajax_webability_acwg_apply_fix', function () {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['msg' => 'Forbidden'], 403);
    }
    check_ajax_referer('webability_acwg_scanner_nonce', 'nonce');

    $index = isset($_POST['fix_index']) ? intval($_POST['fix_index']) : -1;
    $results = get_option(WEBABILITY_SCAN_RESULTS_KEY, []);

    if ($index < 0 || !isset($results[$index])) {
        wp_send_json_error(['msg' => 'Invalid fix index']);
    }

    $fix = $results[$index];
    if ($fix['status'] === 'fixed') {
        wp_send_json_success(['msg' => 'Already fixed']);
    }

    $result = webability_acwg_execute_fix($fix);

    if ($result['success']) {
        $results[$index]['status'] = 'fixed';
        update_option(WEBABILITY_SCAN_RESULTS_KEY, $results, false);
    }

    if ($result['success']) {
        wp_send_json_success(['msg' => $result['msg']]);
    } else {
        wp_send_json_error(['msg' => $result['msg']]);
    }
});

/**
 * AJAX: Apply all auto-fixable issues.
 */
add_action('wp_ajax_webability_acwg_apply_all', function () {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['msg' => 'Forbidden'], 403);
    }
    check_ajax_referer('webability_acwg_scanner_nonce', 'nonce');

    $results = get_option(WEBABILITY_SCAN_RESULTS_KEY, []);
    $applied = 0;
    $failed  = 0;
    $skipped = 0;

    foreach ($results as $i => &$fix) {
        if ($fix['status'] === 'fixed') {
            $skipped++;
            continue;
        }
        if (!$fix['auto_fixable']) {
            $skipped++;
            continue;
        }

        $result = webability_acwg_execute_fix($fix);
        if ($result['success']) {
            $fix['status'] = 'fixed';
            $applied++;
        } else {
            $failed++;
        }
    }
    unset($fix);

    update_option(WEBABILITY_SCAN_RESULTS_KEY, $results, false);

    wp_send_json_success([
        'applied' => $applied,
        'failed'  => $failed,
        'skipped' => $skipped,
    ]);
});

/**
 * Execute a fix based on its target type.
 */
function webability_acwg_execute_fix($fix) {
    switch ($fix['fix_target']) {
        case 'attachment':
            return webability_acwg_fix_attachment($fix);
        case 'post_content':
            return webability_acwg_fix_post_content($fix);
        case 'theme':
            return webability_acwg_fix_theme($fix);
        default:
            return ['success' => false, 'msg' => 'This issue requires manual review'];
    }
}

/**
 * Fix: Update image alt text on a WordPress attachment.
 */
function webability_acwg_fix_attachment($fix) {
    $att_id = intval($fix['wp_object_id']);
    if (!$att_id || !wp_attachment_is_image($att_id)) {
        return ['success' => false, 'msg' => 'Attachment not found'];
    }

    $alt = '';
    if (!empty($fix['attributes']['alt'])) {
        $alt = sanitize_text_field($fix['attributes']['alt']);
    } elseif (!empty($fix['suggested_fix'])) {
        // Extract alt text from suggested fix text
        if (preg_match("/alt=['\"]([^'\"]+)['\"]/", $fix['suggested_fix'], $m)) {
            $alt = sanitize_text_field($m[1]);
        } else {
            $alt = sanitize_text_field($fix['suggested_fix']);
        }
    }

    if (empty($alt)) {
        return ['success' => false, 'msg' => 'No alt text suggestion available'];
    }

    // Backup current value
    webability_acwg_backup('attachment_alt', $att_id, get_post_meta($att_id, '_wp_attachment_image_alt', true));

    update_post_meta($att_id, '_wp_attachment_image_alt', $alt);
    return ['success' => true, 'msg' => 'Alt text updated for image #' . $att_id];
}

/**
 * Fix: Modify post content (headings, links).
 */
function webability_acwg_fix_post_content($fix) {
    $post_id = intval($fix['wp_object_id']);
    if (!$post_id) {
        return ['success' => false, 'msg' => 'Post not found'];
    }

    $post = get_post($post_id);
    if (!$post) {
        return ['success' => false, 'msg' => 'Post not found'];
    }

    $content  = $post->post_content;
    $type     = $fix['issue_type'];
    $modified = false;

    if ($type === 'multiple_h1') {
        $count = 0;
        $content = preg_replace_callback('/<h1(\s[^>]*)?>(.+?)<\/h1>/is', function ($match) use (&$count) {
            $count++;
            if ($count > 1) {
                return '<h2' . $match[1] . '>' . $match[2] . '</h2>';
            }
            return $match[0];
        }, $content);
        $modified = ($count > 1);
    }

    if ($type === 'empty_heading') {
        $content = preg_replace('/<h[1-6][^>]*>\s*<\/h[1-6]>/i', '', $content, -1, $count);
        $modified = ($count > 0);
    }

    if ($type === 'empty_link') {
        if (!empty($fix['attributes']['aria-label'])) {
            $label = esc_attr(sanitize_text_field($fix['attributes']['aria-label']));
            $content = preg_replace_callback('/<a\s([^>]*?)>\s*<\/a>/i', function ($match) use ($label) {
                if (strpos($match[1], 'aria-label') !== false) return $match[0];
                return '<a ' . $match[1] . ' aria-label="' . $label . '"></a>';
            }, $content, 1, $count);
            $modified = ($count > 0);
        }
    }

    if (!$modified) {
        return ['success' => false, 'msg' => 'Could not locate the issue in post content'];
    }

    // Backup only after confirming we have a real modification to apply
    webability_acwg_backup('post_content', $post_id, $post->post_content);

    $result = wp_update_post([
        'ID'           => $post_id,
        'post_content' => $content,
    ], true);

    if (is_wp_error($result)) {
        return ['success' => false, 'msg' => 'Failed to update post: ' . $result->get_error_message()];
    }

    return ['success' => true, 'msg' => 'Post #' . $post_id . ' content updated'];
}

/**
 * Fix: Apply a theme-level structural fix via hooks.
 */
function webability_acwg_fix_theme($fix) {
    $theme_fixes = get_option(WEBABILITY_THEME_FIXES_KEY, []);
    $type = $fix['issue_type'];

    switch ($type) {
        case 'bypass_blocks':
            $theme_fixes['skip_nav'] = true;
            break;
        case 'missing_focus_indicator':
            $theme_fixes['focus_css'] = true;
            break;
        case 'language_of_page':
            $locale = get_locale();
            $theme_fixes['lang_attr'] = substr($locale, 0, 2);
            break;
        default:
            return ['success' => false, 'msg' => 'Unknown theme fix type'];
    }

    update_option(WEBABILITY_THEME_FIXES_KEY, $theme_fixes, false);
    return ['success' => true, 'msg' => 'Theme fix applied: ' . $type];
}

/**
 * Store a backup of the original value before fixing.
 */
function webability_acwg_backup($type, $id, $value) {
    $backups = get_option(WEBABILITY_FIX_BACKUP_KEY, []);
    $key = $type . '_' . $id;
    if (!isset($backups[$key])) {
        $backups[$key] = [
            'type'  => $type,
            'id'    => $id,
            'value' => $value,
            'time'  => current_time('mysql'),
        ];
        update_option(WEBABILITY_FIX_BACKUP_KEY, $backups, false);
    }
}

// ── Theme fix hooks (only fire if the user applied the fix) ──

add_action('wp_body_open', function () {
    $fixes = get_option(WEBABILITY_THEME_FIXES_KEY, []);
    if (!empty($fixes['skip_nav'])) {
        echo '<a class="webability-skip-link" href="#content">' . esc_html__('Skip to content', 'webability-accessibility-widget') . '</a>';
    }
});

add_action('wp_head', function () {
    $fixes = get_option(WEBABILITY_THEME_FIXES_KEY, []);
    if (!empty($fixes['skip_nav'])) {
        echo '<style>.webability-skip-link{position:absolute;top:-40px;left:0;background:#000;color:#fff;padding:8px 16px;z-index:100000;font-size:14px;transition:top .2s}.webability-skip-link:focus{top:0;outline:2px solid #fff}</style>';
    }
    if (!empty($fixes['focus_css'])) {
        echo '<style>*:focus{outline:2px solid #005fcc!important;outline-offset:2px!important}*:focus:not(:focus-visible){outline:none!important}*:focus-visible{outline:2px solid #005fcc!important;outline-offset:2px!important}</style>';
    }
});

add_filter('language_attributes', function ($output) {
    $fixes = get_option(WEBABILITY_THEME_FIXES_KEY, []);
    if (!empty($fixes['lang_attr'])) {
        $lang = esc_attr($fixes['lang_attr']);
        if (strpos($output, 'lang=') === false) {
            $output .= ' lang="' . $lang . '"';
        }
    }
    return $output;
});
