<?php

namespace PixelioCartAbandonRecoveryMore\Frontend\Repositories;


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

use InvalidArgumentException;
use PixelioCartAbandonRecoveryMore\Admin\Wrapper\Pixelio_Cart_Abandon_Recovery_More_Wordpress_Wrapper;
use PixelioCartAbandonRecoveryMore\Includes\Utils\Pixelio_Cart_Abandon_Recovery_More_Util;
use RuntimeException;

class Pixelio_Cart_Abandon_Recovery_More_Email_Templates_Repository
{
	private $wpdb;
	private string $table;
	private Pixelio_Cart_Abandon_Recovery_More_Wordpress_Wrapper $pixelio_wordpress_wrapper;

	public function __construct($pixelio_wordpress_wrapper)
	{
		$this->wpdb = $pixelio_wordpress_wrapper->pixelio_get_wpdb();
		$this->pixelio_wordpress_wrapper = $pixelio_wordpress_wrapper;
		$this->table = $this->wpdb->prefix . Pixelio_Cart_Abandon_Recovery_More_Util::$pixelio_plugin_db_prefix . 'email_templates';
	}

	/*
		**
		* Supprime un template par ID
		*/
	public function delete(int $id): bool
	{
		if ($id <= 0) {
			throw new InvalidArgumentException('Invalid ID');
		}

		if (!$this->exists($id)) {
			throw new RuntimeException('Template not found');
		}

		$updated = $this->wpdb->update(
			$this->table,
			[
				'is_deleted' => 1,
				'synced'     => 0,
				'updated_at' => $this->pixelio_wordpress_wrapper->pixelio_current_time()
			],
			['id' => $id],
			['%d','%d','%s'],
			['%d']
		);

		if ($updated === false) {
			throw new RuntimeException('Failed to delete template');
		}

		return true;
	}

	private function exists(int $id): bool
	{
		$result = $this->wpdb->get_var(
			$this->wpdb->prepare(
				"SELECT id FROM {$this->table} WHERE id = %d",
				$id
			)
		);

		return !empty($result);
	}

	/**
	 * Retrieve all emails from the table, optionally limited.
	 *
	 * Fetches all email records from the database table associated with this model.
	 * Can limit the number of results returned.
	 *
	 * @param int|null $limit Optional. Maximum number of email records to retrieve. Default null (no limit).
	 * @return array|object|\stdClass[]|null Array of email records, array of objects, or null if none found.
	 * @since 1.0.0
	 *
	 */
	public function pixelio_get_all_non_deleted_emails_templates($type)
	{

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$results = $this->wpdb->get_results(
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$this->wpdb->prepare(
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				"SELECT * FROM %i where is_deleted = 0 and type_of_email = %d ORDER BY send_after DESC", $this->table,$type),
			ARRAY_A
		);

		return $results;
	}

	/**
	 * Retrieve all records that have not yet been synced.
	 *
	 * Fetches all rows from the table where the `synced` column is 0.
	 *
	 * @return array|object|\stdClass[]|null Array of unsynced records, or null if none found.
	 * @since 0.1
	 *
	 */
	public function pixelio_get_not_yet_synced()
	{
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared -- safe: must fetch live data, caching not used.
		return $this->wpdb->get_results(
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
			$this->wpdb->prepare("SELECT * FROM %i WHERE synced = %d", $this->table, 0)
		);
	}

	/**
	 * Mark the provided items as synced.
	 *
	 * Iterates over an array of items and sets the `synced` column to 1 for each
	 * valid item in the database table.
	 *
	 * @param array $items Array of objects containing at least an `id` property.
	 * @return bool True if items were processed, false if input is empty or invalid.
	 * @since 0.1
	 *
	 */
	public function pixelio_mark_synced($items)
	{

		if (empty($items) || !is_array($items)) {
			return false;
		}


		foreach ($items as $item) {
			if (isset($item->id) && is_numeric($item->id)) {
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery -- safe: must fetch live data, caching not used.
				$this->wpdb->update(
					$this->table,
					array('synced' => 1),
					array('id' => intval($item->id)),
					array('%d'),
					array('%d')
				);
			}
		}

		return true;
	}

	/**
	 * Retrieve a specific email by ID.
	 *
	 * Fetches a single email record from the database table by its ID.
	 *
	 * @param int $id ID of the email to retrieve.
	 * @return array|null Array of email data if found, null if ID is invalid or not found.
	 * @since 1.0.0
	 *
	 */
	public function pixelio_get_email_by_id($id)
	{

		$id = intval($id);

		if ($id <= 0) {
			return null;
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- safe: must always fetch latest data.
		return $this->wpdb->get_row(
			$this->wpdb->prepare('SELECT * FROM %i WHERE id = %d', $this->table, $this->pixelio_wordpress_wrapper->pixelio_esc_sql($id)),
			ARRAY_A
		);
	}


	/**
	 * Create or update email template
	 */
	public function pixelio_add_or_update_email(array $data): array|RuntimeException
	{
		$data = $this->pixelio_prepare_data($data);

		if (!empty($data['id'])) {
			return $this->pixelio_update_email($data);
		}

		return $this->pixelio_insert_email($data);
	}

	/**
	 * Prepare data array for DB
	 */
	protected function pixelio_prepare_data(array $data): array
	{
		$defaults = [
			'id' => null,
			'template_name' => '',
			'language' => 'fr',
			'subject' => '',
			'body_html' => '',
			'variables' => null,
			'is_active' => 0,
			'send_after' => 0,
			'discount' => 0,
			'discount_type' => 0,
			'discount_expiration_time' => 0,
			'generated_by_ia' => 0,
			'synced' => 0,
			'type_of_email' => 1,
		];

		$data['type_of_email'] = $data['type_of_email'] === 'abandoned_cart' ? 1 : 2;
		$data['is_active'] = !empty($data['is_active']) && $data['generated_by_ia'] === true? 1 : 0;
		$data['generated_by_ia'] = !empty($data['generated_by_ia']) ? 1 : 0;

		$data['variables'] = is_array($data['variables']) ? $this->pixelio_wordpress_wrapper->pixelio_wp_json_encode($data['variables']) : null;
		$data['body_html'] = $this->pixelio_wordpress_wrapper->pixelio_wp_kses($data['body_html'], Pixelio_Cart_Abandon_Recovery_More_Util::$pixelio_cart_abandon_recovery_more_allowed_html);

		return $data;
	}

	/**
	 * Update existing template
	 */
	protected function pixelio_update_email(array $data)
	{
		$update_data = $data;
		unset($update_data['id']); // remove id from update

		$update_data['updated_at'] = $this->pixelio_wordpress_wrapper->pixelio_current_time();

		$updated = $this->wpdb->update(
			$this->table,
			$update_data,
			['id' => (int)$data['id']]
		);

		if ($updated === false) {
			return new RuntimeException('db_error', 'Failed to update template');
		}

		return [
			'id' => (int)$data['id'],
			'updated' => true,
		];
	}

	/**
	 * Insert new template
	 */
	protected function pixelio_insert_email(array $data)
	{
		$data['created_at'] = $this->pixelio_wordpress_wrapper->pixelio_current_time();
		$data['updated_at'] = $this->pixelio_wordpress_wrapper->pixelio_current_time();

		$inserted = $this->wpdb->insert($this->table, $data);
		if (!$inserted) {
			return new RuntimeException('db_error', 'Failed to create template');
		}

		return [
			'id' => $this->wpdb->insert_id,
			'created' => true,
		];
	}

	public function pixelio_increment_sent_stats_by_email($pixelio_cart_abandon_and_more_emails_to_send)
	{

		foreach ($pixelio_cart_abandon_and_more_emails_to_send as $pixelio_cart_abandon_and_more_email) {
			$this->wpdb->query(
				$this->wpdb->prepare(
					"UPDATE %i SET totalSent = totalSent + 1, updated_at = %s WHERE id = %d",
					$this->table,
					$this->pixelio_wordpress_wrapper->pixelio_current_time(),
					$this->pixelio_wordpress_wrapper->pixelio_esc_sql($pixelio_cart_abandon_and_more_email['template_id'])
				)
			);
		}
	}
}
