<?php
/**
 * Plugin Name: APN — Product Update Form field migration (TEMPORARY, DELETE AFTER)
 * Description: Ensures the "Product Update Form" on every site has "Bottle Size" and
 *              "Distillery Location" fields, and renames any legacy "Distillery Address"
 *              field to "Distillery Location". Re-runnable and idempotent. Shows a status
 *              notice on every admin page while installed — delete the file when done.
 * Version:     3.0.0
 *
 * HOW TO USE:
 *   1. Upload this file to wp-content/mu-plugins/ on the target site.
 *   2. Log in as a **Network Super Admin** (multisite) and open any wp-admin page.
 *   3. Read the notice (top of the screen) listing what happened per site.
 *   4. DELETE this file.
 *
 * WHY v3 RE-RUNS (unlike the old version): it no longer sets a permanent "done" flag.
 * It uses a short 5-minute transient only to avoid re-sweeping on every single page
 * load, and it always recomputes/shows the current state. So re-uploading an updated
 * copy just works.
 *
 * Field labels MUST match the bw-winners Product_Update map exactly:
 *   "Bottle Size"         -> meta bottle_size
 *   "Distillery Location" -> meta distillery_location   (was "Distillery Address")
 */

namespace APN\PUM_Migration;

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

const FORM_TITLE      = 'Product Update Form';
const OLD_LOCATION    = 'Distillery Address';   // legacy label to rename
const NEW_LOCATION    = 'Distillery Location';
const STATE_TRANSIENT = 'apn_pum_state_v3';

function fields_to_add() {
	return array(
		array( 'label' => 'Bottle Size',   'type' => 'text', 'description' => '' ),
		array( 'label' => NEW_LOCATION,    'type' => 'text', 'description' => 'City, Country' ),
	);
}

function user_can_run() {
	return is_multisite() ? is_super_admin() : current_user_can( 'manage_options' );
}

add_action( 'admin_init', __NAMESPACE__ . '\\maybe_run', 99 );
add_action( 'network_admin_notices', __NAMESPACE__ . '\\render_notice' );
add_action( 'admin_notices', __NAMESPACE__ . '\\render_notice' );

function maybe_run() {
	if ( ! user_can_run() ) {
		return;
	}
	// Cheap gate: only re-sweep at most every 5 minutes.
	if ( false !== get_site_transient( STATE_TRANSIENT ) ) {
		return;
	}
	if ( ! class_exists( '\\GFAPI' ) ) {
		set_site_transient( STATE_TRANSIENT, array( '__error' => 'Gravity Forms (GFAPI) is not active here — cannot migrate.' ), 300 );
		return;
	}

	$log   = array();
	$sites = is_multisite() ? get_sites( array( 'number' => 0 ) ) : array( (object) array( 'blog_id' => get_current_blog_id() ) );

	foreach ( $sites as $site ) {
		$blog_id = (int) $site->blog_id;
		if ( is_multisite() ) {
			switch_to_blog( $blog_id );
		}

		$site_label = get_bloginfo( 'name' ) . ' (blog ' . $blog_id . ')';
		$form       = find_form_by_title( FORM_TITLE );

		if ( ! $form ) {
			$log[ $blog_id ] = array( 'site' => $site_label, 'status' => 'skipped', 'detail' => 'No "' . FORM_TITLE . '" on this site.' );
		} else {
			$log[ $blog_id ] = process_form( $form, $site_label );
		}

		if ( is_multisite() ) {
			restore_current_blog();
		}
	}

	set_site_transient( STATE_TRANSIENT, $log, 300 );
}

/** First matching form (active or inactive) by title, or null. */
function find_form_by_title( $title ) {
	$forms = array_merge( \GFAPI::get_forms( true, false ), \GFAPI::get_forms( false, false ) );
	foreach ( $forms as $form ) {
		if ( isset( $form['title'] ) && strcasecmp( trim( $form['title'] ), $title ) === 0 ) {
			return $form;
		}
	}
	return null;
}

/** Rename legacy field + add any missing fields. Idempotent. */
function process_form( $form, $site_label ) {
	$actions = array();
	$changed = false;

	// 1) Rename a legacy "Distillery Address" field to "Distillery Location" in place,
	//    preserving its field id so existing entry values stay attached.
	foreach ( $form['fields'] as $field ) {
		if ( isset( $field->label ) && strcasecmp( trim( $field->label ), OLD_LOCATION ) === 0 ) {
			$field->label       = NEW_LOCATION;
			$field->description  = 'City, Country';
			$changed            = true;
			$actions[]          = 'renamed "' . OLD_LOCATION . '" → "' . NEW_LOCATION . '"';
		}
	}

	// 2) Add any target fields still missing (match by label, case-insensitive).
	$existing = array();
	foreach ( $form['fields'] as $field ) {
		if ( isset( $field->label ) ) {
			$existing[ strtolower( trim( $field->label ) ) ] = true;
		}
	}

	$next_id = (int) ( isset( $form['nextFieldId'] ) ? $form['nextFieldId'] : 0 );
	foreach ( $form['fields'] as $field ) {
		if ( isset( $field->id ) ) {
			$next_id = max( $next_id, (int) $field->id + 1 );
		}
	}

	foreach ( fields_to_add() as $spec ) {
		if ( isset( $existing[ strtolower( $spec['label'] ) ] ) ) {
			continue;
		}
		$props = array(
			'id'          => $next_id,
			'formId'      => (int) $form['id'],
			'type'        => $spec['type'],
			'label'       => $spec['label'],
			'adminLabel'  => '',
			'isRequired'  => false,
			'visibility'  => 'visible',
			'description' => isset( $spec['description'] ) ? $spec['description'] : '',
		);
		$form['fields'][] = class_exists( '\\GF_Fields' ) ? \GF_Fields::create( $props ) : $props;
		$existing[ strtolower( $spec['label'] ) ] = true;
		$actions[] = 'added "' . $spec['label'] . '"';
		$next_id++;
		$changed = true;
	}

	if ( ! $changed ) {
		return array( 'site' => $site_label, 'status' => 'ok', 'detail' => 'Both fields already present (form ID ' . (int) $form['id'] . ').' );
	}

	$form['nextFieldId'] = $next_id;
	$res = \GFAPI::update_form( $form );

	if ( is_wp_error( $res ) ) {
		return array( 'site' => $site_label, 'status' => 'ERROR', 'detail' => $res->get_error_message() );
	}
	return array( 'site' => $site_label, 'status' => 'updated', 'detail' => implode( '; ', $actions ) . ' (form ID ' . (int) $form['id'] . ').' );
}

function render_notice() {
	if ( ! user_can_run() ) {
		return;
	}
	$log = get_site_transient( STATE_TRANSIENT );
	if ( false === $log ) {
		return;
	}

	echo '<div class="notice notice-info"><p><strong>APN Product Update Form migration is active.</strong> '
		. 'Delete <code>wp-content/mu-plugins/apn-pum-field-migration.php</code> when the results below look right '
		. '(re-checks every 5 min while installed).</p>';

	if ( isset( $log['__error'] ) ) {
		echo '<p style="color:#b32d2e;">' . esc_html( $log['__error'] ) . '</p></div>';
		return;
	}

	echo '<ul style="margin-left:18px;list-style:disc;">';
	foreach ( $log as $row ) {
		echo '<li><strong>' . esc_html( $row['site'] ) . ':</strong> '
			. esc_html( $row['status'] ) . ' — ' . esc_html( $row['detail'] ) . '</li>';
	}
	echo '</ul></div>';
}
