<?php

namespace EasyCriticalCSS;

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

class Critical_CSS_Regenerate {
	public static function init() {
		self::add_regenerate_hooks();
	}

	public static function expire_post_critical( $post_id, \WP_Post $after, \WP_Post $before ) {
		// We only want real posts.
		if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
			return;
		}

		// if title, content AND excerpt are all identical, do nothing as nothing is really expired.
		if (
			$after->post_title === $before->post_title &&
			$after->post_content === $before->post_content &&
			$after->post_excerpt === $before->post_excerpt
		) {
			return;
		}

		// Expire current post.
		Critical_CSS::expire_individual_css( $post_id );

		// Does the post type have an archive page?
		$post_type        = get_post_type( $post_id );
		$post_type_object = get_post_type_object( $post_type );
		if ( ! empty( $post_type_object->has_archive ) ) {
			$archive_link = get_post_type_archive_link( $post_type );
			if ( ! empty( $archive_link ) ) {
				Critical_CSS::expire_individual_css( $archive_link );
			}
		}
		if ( $post_type === 'post' ) {
			$blog_page_id = get_option( 'page_for_posts' );

			if ( $blog_page_id ) {
				Critical_CSS::expire_individual_css( get_permalink( $blog_page_id ) );
			}
		}

		// Do we need to expire any taxonomies?
		$taxonomies = get_object_taxonomies( $post_type, 'objects' );
		foreach ( $taxonomies as $taxonomy ) {
			// Only expire if the taxonomy is public and has an archive.
			if ( $taxonomy->public && $taxonomy->rewrite ) {
				$terms = get_the_terms( $post_id, $taxonomy->name );

				if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {

					foreach ( $terms as $term ) {
						$term_link = get_term_link( $term );

						if ( ! is_wp_error( $term_link ) ) {
							Critical_CSS::expire_individual_css( $term_link );
						}
					}
				}
			}
		}

		// Expire home page.
		$homepage_id = get_option( 'page_on_front' );
		if ( $homepage_id ) {
			Critical_CSS::expire_individual_css( $homepage_id );
		} else {
			Critical_CSS::expire_individual_css( home_url() );
		}
	}

	public static function expire_archive_critical( $term_id, $taxonomy ) {
		// Expire Critical CSS for an archive.
		$archive_url = get_term_link( $term_id, $taxonomy );
		if ( ! is_wp_error( $archive_url ) ) {
			Critical_CSS::expire_individual_css( $archive_url );
		}
	}

	public static function expire_all_critical_on_update( $upgrader, $options ) {
		// Make sure we are updating.
		if ( $options['action'] !== 'update' ) {
			return;
		}

		// Only expire on our selected updates.
		if ( ! empty( $options['type'] ) && in_array( $options['type'], [ 'core', 'plugin', 'theme' ], true ) ) {
			Critical_CSS::expire_all_css();
		}
	}

	public static function add_regenerate_hooks() {
		$triggers = Settings::get_global_regenerate_triggers();

		// Expire when post updated (post, home page, related archives).
		if ( in_array( 'post_updated', $triggers, true ) ) {
			add_action( 'post_updated', [ __CLASS__, 'expire_post_critical' ], 10, 3 );
		}

		// Expire when a terms's content is updated.
		if ( in_array( 'archive_updated', $triggers, true ) ) {
			add_action( 'edit_term', [ __CLASS__, 'expire_archive_critical' ], 10, 2 );
		}

		// Expire everything when a plugin is (de)activated.
		if ( in_array( 'plugin_change', $triggers, true ) ) {
			add_action( 'activated_plugin', [ 'EasyCriticalCSS\Critical_CSS', 'expire_all_css' ] );
			add_action( 'deactivated_plugin', [ 'EasyCriticalCSS\Critical_CSS', 'expire_all_css' ] );
		}

		// Expire everything with a new theme.
		if ( in_array( 'theme_change', $triggers, true ) ) {
			add_action( 'after_switch_theme', [ 'EasyCriticalCSS\Critical_CSS', 'expire_all_css' ] );
		}

		// Expire everything with an update to core, plugin, or theme.
		if ( in_array( 'upgrader_complete', $triggers, true ) ) {
			add_action( 'upgrader_process_complete', [ __CLASS__, 'expire_all_critical_on_update' ], 10, 2 );
		}
	}
}
