<?php
/**
 * Template manager.
 *
 * @package LoginPageCustomizerAndDesigner
 */

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

/**
 * Class LPCD_Template_Manager
 *
 * CRUD operations for templates in the lpcd_templates table.
 */
class LPCD_Template_Manager {

	/**
	 * Table name (without prefix).
	 *
	 * @var string
	 */
	const TABLE = 'lpcd_templates';

	/**
	 * Maximum custom templates for free version.
	 *
	 * @var int
	 */
	const MAX_CUSTOM_TEMPLATES = 20;

	/**
	 * Create the templates table.
	 */
	public static function create_tables() {
		global $wpdb;

		$table_name      = $wpdb->prefix . self::TABLE;
		$charset_collate = $wpdb->get_charset_collate();

		$sql = "CREATE TABLE {$table_name} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			name VARCHAR(255) NOT NULL,
			type VARCHAR(20) NOT NULL DEFAULT 'custom',
			is_active TINYINT(1) NOT NULL DEFAULT 0,
			json_data LONGTEXT NOT NULL,
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			PRIMARY KEY (id)
		) {$charset_collate};";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $sql );
	}

	/**
	 * Get all templates (listing data, no full JSON).
	 *
	 * @return array List of templates.
	 */
	public static function get_all() {
		global $wpdb;

		$table_name = $wpdb->prefix . self::TABLE;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$rows = $wpdb->get_results(
			$wpdb->prepare( "SELECT id, name, type, is_active, created_at, updated_at FROM %i ORDER BY type ASC, id ASC", $table_name ),
			ARRAY_A
		);

		if ( ! is_array( $rows ) ) {
			return array();
		}

		$templates = array();
		foreach ( $rows as $row ) {
			$templates[] = array(
				'id'        => absint( $row['id'] ),
				'name'      => $row['name'],
				'type'      => $row['type'],
				'isActive'  => (bool) $row['is_active'],
				'createdAt' => $row['created_at'],
				'updatedAt' => $row['updated_at'],
			);
		}

		return $templates;
	}

	/**
	 * Get a single template with full JSON data.
	 *
	 * @param int $id Template ID.
	 * @return array|null Template data or null.
	 */
	public static function get( $id ) {
		global $wpdb;

		$table_name = $wpdb->prefix . self::TABLE;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$row = $wpdb->get_row(
			$wpdb->prepare( "SELECT * FROM %i WHERE id = %d", $table_name, $id ),
			ARRAY_A
		);

		if ( ! $row ) {
			return null;
		}

		$json_data = json_decode( $row['json_data'], true );
		if ( ! is_array( $json_data ) ) {
			$json_data = array();
		}

		return array(
			'id'       => absint( $row['id'] ),
			'name'     => $row['name'],
			'type'     => $row['type'],
			'isActive' => (bool) $row['is_active'],
			'jsonData' => $json_data,
		);
	}

	/**
	 * Create a new custom template.
	 *
	 * @param string $name      Template name.
	 * @param array  $json_data Template data.
	 * @return int|WP_Error New template ID or error.
	 */
	public static function create( $name, $json_data ) {
		global $wpdb;

		// Check limit.
		$custom_count = self::get_custom_count();
		if ( $custom_count >= self::MAX_CUSTOM_TEMPLATES ) {
			return new WP_Error(
				'lpcd_limit_reached',
				sprintf(
					/* translators: %d: Maximum number of custom templates. */
					__( 'You can create a maximum of %d custom templates.', 'login-page-customizer-and-designer' ),
					self::MAX_CUSTOM_TEMPLATES
				)
			);
		}

		$name     = sanitize_text_field( $name );
		$sanitized = LPCD_Sanitizer::sanitize_template_json( $json_data );

		if ( is_wp_error( $sanitized ) ) {
			return $sanitized;
		}

		$table_name = $wpdb->prefix . self::TABLE;
		$now        = gmdate( 'Y-m-d H:i:s' );

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		$result = $wpdb->insert(
			$table_name,
			array(
				'name'       => $name,
				'type'       => 'custom',
				'is_active'  => 0,
				'json_data'  => wp_json_encode( $sanitized ),
				'created_at' => $now,
				'updated_at' => $now,
			),
			array( '%s', '%s', '%d', '%s', '%s', '%s' )
		);

		if ( false === $result ) {
			return new WP_Error(
				'lpcd_db_error',
				__( 'Failed to create template.', 'login-page-customizer-and-designer' )
			);
		}

		return absint( $wpdb->insert_id );
	}

	/**
	 * Update an existing template.
	 *
	 * @param int    $id        Template ID.
	 * @param string $name      Template name.
	 * @param array  $json_data Template data.
	 * @return bool|WP_Error True on success.
	 */
	public static function update( $id, $name, $json_data ) {
		global $wpdb;

		$template = self::get( $id );
		if ( ! $template ) {
			return new WP_Error(
				'lpcd_not_found',
				__( 'Template not found.', 'login-page-customizer-and-designer' )
			);
		}

		$name      = sanitize_text_field( $name );
		$sanitized = LPCD_Sanitizer::sanitize_template_json( $json_data );

		if ( is_wp_error( $sanitized ) ) {
			return $sanitized;
		}

		// Block free users from saving changes to Pro templates.
		$free_templates = array( 'Light Centered', 'Dark Centered' );
		if ( ! lpcd_is_pro() && 'custom' !== $template['type'] && ! in_array( $template['name'], $free_templates, true ) ) {
			return new WP_Error(
				'lpcd_pro_required',
				__( 'This is a Pro template. Please upgrade to customize it.', 'login-page-customizer-and-designer' )
			);
		}

		$table_name = $wpdb->prefix . self::TABLE;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$result = $wpdb->update(
			$table_name,
			array(
				'name'       => $name,
				'json_data'  => wp_json_encode( $sanitized ),
				'updated_at' => gmdate( 'Y-m-d H:i:s' ),
			),
			array( 'id' => $id ),
			array( '%s', '%s', '%s' ),
			array( '%d' )
		);

		if ( false === $result ) {
			return new WP_Error(
				'lpcd_db_error',
				__( 'Failed to update template.', 'login-page-customizer-and-designer' )
			);
		}

		return true;
	}

	/**
	 * Delete a custom template.
	 *
	 * @param int $id Template ID.
	 * @return bool|WP_Error True on success.
	 */
	public static function delete( $id ) {
		global $wpdb;

		$template = self::get( $id );
		if ( ! $template ) {
			return new WP_Error(
				'lpcd_not_found',
				__( 'Template not found.', 'login-page-customizer-and-designer' )
			);
		}

		if ( 'free' === $template['type'] || 'advanced' === $template['type'] ) {
			return new WP_Error(
				'lpcd_cannot_delete',
				__( 'Built-in templates cannot be deleted.', 'login-page-customizer-and-designer' )
			);
		}

		$table_name = $wpdb->prefix . self::TABLE;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->delete( $table_name, array( 'id' => $id ), array( '%d' ) );

		return true;
	}

	/**
	 * Activate a template (deactivate all others).
	 *
	 * @param int $id Template ID.
	 * @return bool|WP_Error True on success.
	 */
	public static function activate( $id ) {
		global $wpdb;

		$template = self::get( $id );
		if ( ! $template ) {
			return new WP_Error(
				'lpcd_not_found',
				__( 'Template not found.', 'login-page-customizer-and-designer' )
			);
		}

		// Block free users from activating Pro templates.
		$free_templates = array( 'Light Centered', 'Dark Centered' );
		if ( ! lpcd_is_pro() && 'custom' !== $template['type'] && ! in_array( $template['name'], $free_templates, true ) ) {
			return new WP_Error(
				'lpcd_pro_required',
				__( 'This is a Pro template. Please upgrade to activate it.', 'login-page-customizer-and-designer' )
			);
		}

		$table_name = $wpdb->prefix . self::TABLE;

		// Deactivate all.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->query(
			$wpdb->prepare( "UPDATE %i SET is_active = 0 WHERE is_active = %d", $table_name, 1 )
		);

		// Activate this one.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->update(
			$table_name,
			array( 'is_active' => 1 ),
			array( 'id' => $id ),
			array( '%d' ),
			array( '%d' )
		);

		return true;
	}

	/**
	 * Get the currently active template.
	 *
	 * @return array|null Active template with JSON data, or null.
	 */
	public static function get_active() {
		global $wpdb;

		$table_name = $wpdb->prefix . self::TABLE;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$row = $wpdb->get_row(
			$wpdb->prepare( "SELECT * FROM %i WHERE is_active = %d LIMIT 1", $table_name, 1 ),
			ARRAY_A
		);

		if ( ! $row ) {
			return null;
		}

		$json_data = json_decode( $row['json_data'], true );
		if ( ! is_array( $json_data ) ) {
			$json_data = array();
		}

		return array(
			'id'       => absint( $row['id'] ),
			'name'     => $row['name'],
			'type'     => $row['type'],
			'isActive' => true,
			'jsonData' => $json_data,
		);
	}

	/**
	 * Count custom (user-created) templates.
	 *
	 * @return int Count.
	 */
	public static function get_custom_count() {
		global $wpdb;

		$table_name = $wpdb->prefix . self::TABLE;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$count = $wpdb->get_var(
			$wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE type = %s", $table_name, 'custom' )
		);

		return absint( $count );
	}

	/**
	 * Reset a premade template to its original JSON state.
	 *
	 * @param int $id Template ID.
	 * @return bool|WP_Error True on success.
	 */
	public static function reset( $id ) {
		global $wpdb;

		$template = self::get( $id );
		if ( ! $template ) {
			return new WP_Error(
				'lpcd_not_found',
				__( 'Template not found.', 'login-page-customizer-and-designer' )
			);
		}

		if ( 'free' !== $template['type'] && 'advanced' !== $template['type'] ) {
			return new WP_Error(
				'lpcd_cannot_reset',
				__( 'Only premade templates can be reset.', 'login-page-customizer-and-designer' )
			);
		}

		// Find the matching JSON file in the correct directory.
		$type_dir      = 'advanced' === $template['type'] ? 'advanced' : 'free';
		$templates_dir = LPCD_DIR . 'templates/' . $type_dir . '/';
		$template_file = '';

		if ( is_dir( $templates_dir ) ) {
			$files = glob( $templates_dir . '*.json' );
			if ( is_array( $files ) ) {
				foreach ( $files as $file ) {
					$raw_check = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
					if ( ! $raw_check ) {
						continue;
					}
					$d = json_decode( $raw_check, true );
					if ( is_array( $d ) && isset( $d['name'] ) && $d['name'] === $template['name'] ) {
						$template_file = $file;
						break;
					}
				}
			}
		}

		if ( empty( $template_file ) || ! file_exists( $template_file ) ) {
			return new WP_Error(
				'lpcd_file_not_found',
				__( 'Original template file not found.', 'login-page-customizer-and-designer' )
			);
		}

		$raw = file_get_contents( $template_file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
		if ( ! $raw ) {
			return new WP_Error(
				'lpcd_read_error',
				__( 'Failed to read original template file.', 'login-page-customizer-and-designer' )
			);
		}

		$data = json_decode( $raw, true );
		if ( ! is_array( $data ) ) {
			return new WP_Error(
				'lpcd_invalid_json',
				__( 'Original template file contains invalid JSON.', 'login-page-customizer-and-designer' )
			);
		}

		// Update DB.
		$table_name = $wpdb->prefix . self::TABLE;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->update(
			$table_name,
			array(
				'json_data'  => wp_json_encode( $data ),
				'updated_at' => gmdate( 'Y-m-d H:i:s' ),
			),
			array( 'id' => $id ),
			array( '%s', '%s' ),
			array( '%d' )
		);

		return true;
	}

	/**
	 * Seed all built-in templates (free + advanced).
	 *
	 * Also inserts any new templates not yet in the database.
	 */
	public static function seed_free_templates() {
		self::seed_templates_from_dir( 'free' );
		self::seed_templates_from_dir( 'advanced' );
	}

	/**
	 * Seed built-in templates from a specific directory.
	 *
	 * @param string $type Template type ('free' or 'advanced').
	 */
	private static function seed_templates_from_dir( $type ) {
		global $wpdb;

		$table_name = $wpdb->prefix . self::TABLE;

		$templates_dir = LPCD_DIR . 'templates/' . $type . '/';

		if ( ! is_dir( $templates_dir ) ) {
			return;
		}

		$files = glob( $templates_dir . '*.json' );
		if ( ! is_array( $files ) ) {
			return;
		}

		// Get existing template names for this type.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$existing_names = $wpdb->get_col(
			$wpdb->prepare( "SELECT name FROM %i WHERE type = %s", $table_name, $type )
		);

		// Collect names from JSON files.
		$file_names = array();
		foreach ( $files as $file ) {
			$raw = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
			if ( ! $raw ) {
				continue;
			}
			$d = json_decode( $raw, true );
			if ( is_array( $d ) && isset( $d['name'] ) ) {
				$file_names[] = sanitize_text_field( $d['name'] );
			}
		}

		// Remove orphaned templates (exist in DB but no longer on disk).
		foreach ( $existing_names as $ename ) {
			if ( ! in_array( $ename, $file_names, true ) ) {
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				$wpdb->delete(
					$table_name,
					array(
						'name' => $ename,
						'type' => $type,
					),
					array( '%s', '%s' )
				);
			}
		}

		$has_any = ! empty( $file_names );
		$now     = gmdate( 'Y-m-d H:i:s' );

		foreach ( $files as $file ) {
			$raw = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
			if ( ! $raw ) {
				continue;
			}

			$data = json_decode( $raw, true );
			if ( ! is_array( $data ) || ! isset( $data['name'] ) ) {
				continue;
			}

			$name = sanitize_text_field( $data['name'] );

			// Skip if already seeded.
			if ( in_array( $name, $existing_names, true ) ) {
				continue;
			}

			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			$wpdb->insert(
				$table_name,
				array(
					'name'       => $name,
					'type'       => $type,
					'is_active'  => ! $has_any ? 1 : 0,
					'json_data'  => wp_json_encode( $data ),
					'created_at' => $now,
					'updated_at' => $now,
				),
				array( '%s', '%s', '%d', '%s', '%s', '%s' )
			);

			$has_any = true;
		}
	}
}
