<?php
if ( ! defined( 'ABSPATH' ) ) exit;
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- AJAX handler; all variables are local to this file
// phpcs:disable WordPress.Security.ValidatedSanitizedInput -- inputs sanitized via sanitize_text_field/wp_unslash/intval at point of use

check_ajax_referer( 'scholar_sync_save_author_profile', 'nonce' );

if ( ! current_user_can( 'edit_others_posts' ) ) {
    wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'scholar-sync' ) ) );
}

$scholar_id   = isset( $_POST['scholar_id'] )     ? sanitize_text_field( wp_unslash( $_POST['scholar_id'] ) )    : '';
$name         = isset( $_POST['name'] )           ? sanitize_text_field( wp_unslash( $_POST['name'] ) )          : '';
$affiliations = isset( $_POST['affiliations'] )   ? sanitize_text_field( wp_unslash( $_POST['affiliations'] ) )  : '';
$h_index      = isset( $_POST['h_index'] )        ? (int) $_POST['h_index']                                      : 0;
$citations    = isset( $_POST['citations'] )      ? (int) $_POST['citations']                                    : 0;
$i10_index    = isset( $_POST['i10_index'] )      ? (int) $_POST['i10_index']                                    : 0;
$interests    = isset( $_POST['interests'] )      ? sanitize_text_field( wp_unslash( $_POST['interests'] ) )     : '';
$counts_raw   = isset( $_POST['counts_by_year'] ) ? wp_unslash( $_POST['counts_by_year'] )                       : '';

if ( empty( $scholar_id ) || empty( $name ) ) {
    wp_send_json_error( array( 'message' => __( 'Missing required fields.', 'scholar-sync' ) ) );
}

// Validate and re-encode counts_by_year: only accept integer year keys (1900–2100)
// with non-negative integer citation counts. Rejects any non-numeric or out-of-range data.
$per_year = null;
if ( ! empty( $counts_raw ) ) {
    $decoded = json_decode( $counts_raw, true );
    if ( is_array( $decoded ) && ! empty( $decoded ) ) {
        $validated = array();
        foreach ( $decoded as $year => $count ) {
            $year_int = absint( $year );
            if ( $year_int >= 1900 && $year_int <= 2100 ) {
                $validated[ $year_int ] = absint( $count );
            }
        }
        if ( ! empty( $validated ) ) {
            $per_year = wp_json_encode( $validated );
        }
    }
}

global $wpdb;
$table = SCHOLAR_SYNC_DB_AUTHORS;

// Reject if this scholar_id already exists.
$existing_id = (int) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- %i is the WordPress identifier placeholder (WP 6.2+)
        'SELECT author_id FROM %i WHERE scholar_id = %s LIMIT 1',
        $table,
        $scholar_id
    )
);
if ( $existing_id ) {
    wp_send_json_error( array( 'message' => __( 'Researcher already exists.', 'scholar-sync' ) ) );
}

// Store 0 as NULL — distinguishes "not provided by service" from a real zero.
$wpdb->insert( $table, array( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Insert bypasses cache safely
    'scholar_id'    => $scholar_id,
    'name'          => $name,
    'affiliations'  => $affiliations,
    'website'       => '',
    'h_index_all'   => $h_index   > 0 ? $h_index   : null,
    'citations_all' => $citations > 0 ? $citations : null,
    'i10_index_all' => $i10_index > 0 ? $i10_index : null,
    'interests'     => $interests !== '' ? $interests : null,
    'per_year'      => $per_year,
) );

$author_id = (int) $wpdb->insert_id;
if ( ! $author_id ) {
    wp_send_json_error( array( 'message' => __( 'Failed to save author profile. Please try again.', 'scholar-sync' ) ) );
}

wp_send_json_success( array( 'author_id' => $author_id, 'scholar_id' => $scholar_id ) );
