<?php
/**
 * This file is part of the Wisewand WordPress plugin.
 *
 * @package Wisewand
 * @since 1.0.0
 * @license GPL-2.0-or-later
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
namespace Wisewand\RSS;

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use WP_Error;
use Wisewand\Calendar\Calendar_Entry_Manager;
use Wisewand\Logging\Logger;

// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Table name stored in class property from $wpdb->prefix is safe to interpolate; direct database calls required for custom plugin table operations

/**
 * Bridge service class between RSS and Editorial Calendar systems.
 *
 * This class handles the integration between RSS articles and calendar entries,
 * allowing RSS-sourced articles to appear in the editorial calendar with
 * visual differentiation and limited editability.
 *
 * @since 1.0.0
 */
class RSS_Calendar_Bridge {

	/**
	 * Calendar Entry Manager instance.
	 *
	 * @var Calendar_Entry_Manager
	 */
	private $calendar_manager;

	/**
	 * RSS Article Manager instance.
	 *
	 * @var RSS_Article_Manager
	 */
	private $article_manager;

	/**
	 * RSS Feed Manager instance.
	 *
	 * @var RSS_Feed_Manager
	 */
	private $feed_manager;

	/**
	 * Logger instance.
	 *
	 * @var Logger
	 */
	private $logger;

	/**
	 * Editorial calendar table name.
	 *
	 * @var string
	 */
	private $calendar_table;

	/**
	 * Constructor.
	 *
	 * @param Calendar_Entry_Manager $calendar_manager Calendar entry manager instance.
	 * @param RSS_Article_Manager    $article_manager  RSS article manager instance.
	 * @param RSS_Feed_Manager       $feed_manager     RSS feed manager instance.
	 * @param Logger                 $logger           Logger instance.
	 */
	public function __construct(
		Calendar_Entry_Manager $calendar_manager,
		RSS_Article_Manager $article_manager,
		RSS_Feed_Manager $feed_manager,
		Logger $logger
	) {
		global $wpdb;
		$this->calendar_manager = $calendar_manager;
		$this->article_manager  = $article_manager;
		$this->feed_manager     = $feed_manager;
		$this->logger           = $logger;
		$this->calendar_table   = $wpdb->prefix . 'wisewand_editorial_calendar';
	}

	/**
	 * Create a calendar entry for an RSS article.
	 *
	 * This method converts an RSS article with a scheduled publication time
	 * into an editorial calendar entry with visual differentiation (📡 emoji,
	 * green color #10b981).
	 *
	 * @param array $article RSS article data from database (must include id, feed_id, scheduled_publish_time).
	 * @param array $feed    RSS feed data from database (must include feed_name, feed_icon).
	 *
	 * @return int|WP_Error Calendar entry ID on success, WP_Error on failure.
	 */
	public function create_calendar_entry_for_rss_article( $article, $feed ) {
		// Validate required article fields.
		if ( empty( $article['id'] ) || empty( $article['feed_id'] ) || empty( $article['scheduled_publish_time'] ) ) {
			return new WP_Error(
				'invalid_article_data',
				'RSS article must have id, feed_id, and scheduled_publish_time'
			);
		}

		// Validate required feed fields.
		if ( empty( $feed['feed_name'] ) ) {
			return new WP_Error( 'invalid_feed_data', 'RSS feed must have feed_name' );
		}

		// Check if calendar entry already exists for this article.
		$existing_entry = $this->get_calendar_entry_by_rss_article( $article['id'] );
		if ( $existing_entry ) {
			$this->logger->info(
				'Calendar entry already exists for RSS article',
				array(
					'article_id'       => $article['id'],
					'calendar_entry'   => $existing_entry['id'],
					'publication_date' => $existing_entry['publication_date'],
				)
			);
			return $existing_entry['id'];
		}

		// Prepare source metadata for visual differentiation.
		$source_metadata = wp_json_encode(
			array(
				'feed_name'  => $feed['feed_name'],
				'feed_icon'  => $feed['feed_icon'] ?? '📡', // Default to satellite emoji.
				'feed_color' => '#10b981', // Green color for RSS entries.
				'source'     => 'rss',
			)
		);

		// Build calendar entry data.
		$entry_data = array(
			'keyword'             => '📡 ' . ( $article['article_title'] ?? 'RSS Article' ),
			'publication_date'    => $article['scheduled_publish_time'],
			'publication_time'    => $article['scheduled_publish_time'], // CRITICAL: Also set publication_time for time display
			'keyword_source'      => 'rss',
			'rss_article_id'      => $article['id'],
			'rss_feed_id'         => $article['feed_id'],
			'source_metadata'     => $source_metadata,
			'wisewand_article_id' => $article['wisewand_article_id'] ?? null,
			'wisewand_status'     => $article['import_status'] ?? 'pending',
			'publication_action'  => 'auto',
			'auto_publish'        => 1,
			'publish_as_draft'    => 0,
			'created_by'          => 0, // System-created (RSS import).
			'wisewand_payload'    => '{}', // Empty JSON object for RSS articles (no payload needed).
		);

		// Add optional fields if available.
		if ( ! empty( $feed['target_post_type'] ) ) {
			$entry_data['target_post_type'] = $feed['target_post_type'];
		}
		if ( ! empty( $feed['target_author'] ) ) {
			$entry_data['target_author'] = $feed['target_author'];
		}
		if ( ! empty( $feed['target_categories'] ) ) {
			$entry_data['target_category'] = $feed['target_categories'];
		}
		if ( ! empty( $feed['target_tags'] ) ) {
			$entry_data['target_tags'] = $feed['target_tags'];
		}

		// Create calendar entry.
		$entry_id = $this->calendar_manager->create_entry( $entry_data );

		if ( is_wp_error( $entry_id ) ) {
			$this->logger->error(
				'Failed to create calendar entry for RSS article',
				array(
					'article_id' => $article['id'],
					'error'      => $entry_id->get_error_message(),
				)
			);
			return $entry_id;
		}

		$this->logger->info(
			'Created calendar entry for RSS article',
			array(
				'article_id'       => $article['id'],
				'feed_id'          => $article['feed_id'],
				'calendar_entry'   => $entry_id,
				'publication_date' => $article['scheduled_publish_time'],
			)
		);

		return $entry_id;
	}

	/**
	 * Update the scheduled publication time for an RSS calendar entry.
	 *
	 * This allows users to edit the publication date/time for RSS-sourced
	 * calendar entries. Only the publication_date field can be edited.
	 *
	 * @param int    $calendar_entry_id Calendar entry ID.
	 * @param string $new_publish_time  New publication time (MySQL datetime format).
	 *
	 * @return bool|WP_Error True on success, WP_Error on failure.
	 */
	public function update_calendar_entry_time( $calendar_entry_id, $new_publish_time ) {
		// Validate calendar entry exists and is RSS-sourced.
		$entry = $this->calendar_manager->get_entry( $calendar_entry_id );
		if ( ! $entry ) {
			return new WP_Error( 'entry_not_found', 'Calendar entry not found' );
		}

		if ( $entry['keyword_source'] !== 'rss' ) {
			return new WP_Error( 'not_rss_entry', 'Calendar entry is not RSS-sourced' );
		}

		// Validate datetime format.
		$datetime = \DateTime::createFromFormat( 'Y-m-d H:i:s', $new_publish_time );
		if ( ! $datetime ) {
			return new WP_Error( 'invalid_datetime', 'Invalid datetime format. Use Y-m-d H:i:s' );
		}

		// Update only the publication_date field.
		$result = $this->calendar_manager->update_entry(
			$calendar_entry_id,
			array( 'publication_date' => $new_publish_time )
		);

		if ( false === $result ) {
			$this->logger->error(
				'Failed to update RSS calendar entry time',
				array(
					'entry_id'         => $calendar_entry_id,
					'new_publish_time' => $new_publish_time,
				)
			);
			return new WP_Error( 'update_failed', 'Failed to update calendar entry' );
		}

		$this->logger->info(
			'Updated RSS calendar entry publication time',
			array(
				'entry_id' => $calendar_entry_id,
				'old_time' => $entry['publication_date'],
				'new_time' => $new_publish_time,
			)
		);

		return true;
	}

	/**
	 * Delete a calendar entry for an RSS article.
	 *
	 * This only deletes the calendar entry, NOT the RSS article tracking record.
	 * The RSS article will remain in the RSS system and can be re-added to
	 * the calendar later.
	 *
	 * @param int $calendar_entry_id Calendar entry ID to delete.
	 *
	 * @return bool|WP_Error True on success, WP_Error on failure.
	 */
	public function delete_calendar_entry( $calendar_entry_id ) {
		// Validate calendar entry exists and is RSS-sourced.
		$entry = $this->calendar_manager->get_entry( $calendar_entry_id );
		if ( ! $entry ) {
			return new WP_Error( 'entry_not_found', 'Calendar entry not found' );
		}

		if ( $entry['keyword_source'] !== 'rss' ) {
			return new WP_Error( 'not_rss_entry', 'Calendar entry is not RSS-sourced' );
		}

		// Log the deletion (keeping RSS article ID for reference).
		$this->logger->info(
			'Deleting RSS calendar entry (keeping RSS article tracking)',
			array(
				'calendar_entry' => $calendar_entry_id,
				'rss_article_id' => $entry['rss_article_id'],
				'rss_feed_id'    => $entry['rss_feed_id'],
			)
		);

		// Delete the calendar entry.
		$result = $this->calendar_manager->delete_entry( $calendar_entry_id );

		if ( false === $result ) {
			$this->logger->error(
				'Failed to delete RSS calendar entry',
				array( 'entry_id' => $calendar_entry_id )
			);
			return new WP_Error( 'delete_failed', 'Failed to delete calendar entry' );
		}

		return true;
	}

	/**
	 * Sync RSS articles to calendar for a specific feed.
	 *
	 * This creates calendar entries for all RSS articles that have a
	 * scheduled_publish_time but no corresponding calendar entry yet.
	 *
	 * @param int $feed_id     RSS feed ID to sync articles from.
	 * @param int $limit       Maximum number of articles to sync (default: 50).
	 *
	 * @return array Array with 'success' count and 'errors' array.
	 */
	public function sync_rss_to_calendar( $feed_id, $limit = 50 ) {
		$results = array(
			'success' => 0,
			'errors'  => array(),
			'skipped' => 0,
		);

		// Get feed data.
		$feed = $this->feed_manager->get_feed( $feed_id );
		if ( ! $feed ) {
			$results['errors'][] = 'Feed not found: ' . $feed_id;
			return $results;
		}

		// Get articles with scheduled publish times that aren't in calendar yet.
		$articles = $this->get_rss_articles_not_in_calendar( $feed_id, $limit );

		$this->logger->info(
			'Starting RSS to calendar sync',
			array(
				'feed_id'        => $feed_id,
				'feed_name'      => $feed['feed_name'],
				'articles_found' => count( $articles ),
			)
		);

		foreach ( $articles as $article ) {
			// Skip articles without scheduled publish time.
			if ( empty( $article['scheduled_publish_time'] ) ) {
				++$results['skipped'];
				continue;
			}

			// Create calendar entry.
			$entry_id = $this->create_calendar_entry_for_rss_article( $article, $feed );

			if ( is_wp_error( $entry_id ) ) {
				$results['errors'][] = sprintf(
					'Article %d: %s',
					$article['id'],
					$entry_id->get_error_message()
				);
			} else {
				++$results['success'];
			}
		}

		$this->logger->info(
			'RSS to calendar sync completed',
			array(
				'feed_id' => $feed_id,
				'success' => $results['success'],
				'errors'  => count( $results['errors'] ),
				'skipped' => $results['skipped'],
			)
		);

		return $results;
	}

	/**
	 * Get calendar entry by RSS article ID.
	 *
	 * @param int $rss_article_id RSS article ID.
	 *
	 * @return array|null Calendar entry data or null if not found.
	 */
	public function get_calendar_entry_by_rss_article( $rss_article_id ) {
		global $wpdb;

		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$entry = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT * FROM {$this->calendar_table} WHERE rss_article_id = %d LIMIT 1",
				$rss_article_id
			),
			ARRAY_A
		);

		return $entry ? $entry : null;
	}

	/**
	 * Get RSS articles that have scheduled publish times but no calendar entry.
	 *
	 * @param int $feed_id RSS feed ID.
	 * @param int $limit   Maximum number of articles to retrieve.
	 *
	 * @return array Array of RSS article records.
	 */
	private function get_rss_articles_not_in_calendar( $feed_id, $limit = 50 ) {
		global $wpdb;

		$articles_table = $wpdb->prefix . 'wisewand_rss_articles';

		// Get articles with scheduled_publish_time that don't have calendar entries.
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$articles = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT a.*
				FROM {$articles_table} a
				LEFT JOIN {$this->calendar_table} c ON a.id = c.rss_article_id
				WHERE a.feed_id = %d
				AND a.scheduled_publish_time IS NOT NULL
				AND a.import_status IN ('pending', 'imported')
				AND c.id IS NULL
				ORDER BY a.scheduled_publish_time ASC
				LIMIT %d",
				$feed_id,
				$limit
			),
			ARRAY_A
		);

		return $articles ? $articles : array();
	}

	/**
	 * Batch sync all feeds to calendar.
	 *
	 * This syncs RSS articles from all active feeds to the editorial calendar.
	 * Useful for scheduled CRON jobs.
	 *
	 * @param int $articles_per_feed Maximum articles to sync per feed (default: 20).
	 *
	 * @return array Summary of sync results across all feeds.
	 */
	public function sync_all_feeds_to_calendar( $articles_per_feed = 20 ) {
		$summary = array(
			'feeds_processed' => 0,
			'total_success'   => 0,
			'total_errors'    => 0,
			'total_skipped'   => 0,
		);

		// Get all active feeds with auto_import enabled.
		$feeds = $this->feed_manager->get_all_feeds(
			array(
				'auto_import_enabled' => 1,
				'is_active'           => 1,
			)
		);

		$this->logger->info(
			'Starting batch sync of all feeds to calendar',
			array( 'feeds_count' => count( $feeds ) )
		);

		foreach ( $feeds as $feed ) {
			$results = $this->sync_rss_to_calendar( $feed['id'], $articles_per_feed );

			++$summary['feeds_processed'];
			$summary['total_success'] += $results['success'];
			$summary['total_errors']  += count( $results['errors'] );
			$summary['total_skipped'] += $results['skipped'];
		}

		$this->logger->info(
			'Batch sync to calendar completed',
			$summary
		);

		return $summary;
	}
}
