<?php

namespace NewsletterBridge\Config;

use NewsletterBridge\Config\NewsletterConfig;
use NewsletterBridge\Config\SiteConfig;

/**
 * Classe per le query della newsletter
 * Esegue query direttamente sul database WordPress
 */
class Queries {

    private $feed;
    private $tags;
    private $args;
    private $feed_length;
    private $response;
    private bool $preview;
    private $config;


    public function __construct( string $feed_type, int $feed_length = 40, string $tag = '', bool $preview = false ) {
        $this->feed_length = $feed_length;
        $this->preview     = $preview;
        $this->config      = NewsletterConfig::getConfig();
        
        $this->tags = $this->getTagIDS( $tag );
        $this->args = $this->getQueryBasicArgs();

        switch($feed_type) {
            case 'subject':
            case 'summary':
                $this->response = $this->$feed_type();
                break;
            default:
                // Per i feed dinamici, usa il metodo generico o quello specifico se esiste
                if (method_exists($this, $feed_type)) {
                    $this->feed = $this->$feed_type();
                } else {
                    $this->feed = $this->getGenericFeed($feed_type);
                }
                $this->response = $this->getRSS();
                break;
        }
    }

    function getResponse() {
        return $this->response;
    }
    
    /**
     * Metodo generico per gestire tutti i feed dinamici
     */
    private function getGenericFeed($feed_name) {
        $args = $this->buildQueryArgs($feed_name);
        
        $posts = get_posts($args);
        $result = $this->getTemplatePosts($posts);
        
        foreach ($result as $post) {
            $this->markPostAsUsed($post->id);
        }

        return $result;
    }
    
    private function getFeedConfig($feed_name) {
        foreach ($this->config->feeds as $feed) {
            if ($feed->name === $feed_name) {
                return $feed;
            }
        }
        return null;
    }
    
    private function excludeUsedPosts($args) {
        $used_posts = $this->getUsedPosts();
        if (!empty($used_posts)) {
            $args['post__not_in'] = array_merge(
                $args['post__not_in'] ?? [],
                $used_posts
            );
        }
        return $args;
    }
    
    private function markPostAsUsed($post_id) {
        $used_posts = $this->getUsedPosts();
        if (!in_array($post_id, $used_posts)) {
            $used_posts[] = $post_id;
            $this->saveUsedPosts($used_posts);
        }
    }
    
    /**
     * Recupera i post utilizzati dal transient
     */
    private function getUsedPosts() {
        return get_transient('newsletter_used_posts') ?: [];
    }
    
    /**
     * Salva i post utilizzati nel transient (24 ore di durata)
     */
    private function saveUsedPosts($used_posts) {
        set_transient('newsletter_used_posts', $used_posts, 24 * HOUR_IN_SECONDS);
    }
    
    /**
     * Resetta l'array dei post utilizzati (utile per iniziare una nuova newsletter)
     */
    public static function resetUsedPosts() {
        delete_transient('newsletter_used_posts');
    }
    
    /**
     * Debug: mostra quanti post sono stati utilizzati
     */
    public static function getUsedPostsCount() {
        $used_posts = get_transient('newsletter_used_posts') ?: [];
        return count($used_posts);
    }
    
    /**
     * Genera tutti i feed in una singola chiamata per mantenere l'esclusione dei post
     */
    public static function generateAllFeeds($config, $preview = false) {
        $feeds = [];
        
        // Genera i feed di sistema
        $feeds['subject'] = self::generateSingleFeed('subject', $config, $preview);
        $feeds['summary'] = self::generateSingleFeed('summary', $config, $preview);
        
        // Genera i feed configurati
        foreach ($config->feeds as $feed) {
            $feeds[$feed->name] = self::generateSingleFeed($feed->name, $config, $preview);
        }
        
        return $feeds;
    }
    
    /**
     * Genera un singolo feed mantenendo l'esclusione dei post
     */
    private static function generateSingleFeed($feed_name, $config, $preview = false) {
        $queries = new self($feed_name, 40, '', $preview);
        return $queries->getResponse();
    }
    
    private function buildQueryArgs($feed_name, $additional_args = []) {
        $feed_config = $this->getFeedConfig($feed_name);
        if (!$feed_config || !isset($feed_config->query_params)) {
            return $this->args;
        }
        
        $query_params = $feed_config->query_params;
        $args = $this->getQueryBasicArgs();
        
        if (isset($query_params->posts_per_page)) {
            $args['posts_per_page'] = $query_params->posts_per_page;
        }
        
        // Compatibilità con vecchi nomi (include_tags) e nuovi (include_taxonomies)
        $include_taxonomies = $query_params->include_taxonomies ?? $query_params->include_tags ?? null;
        if ($include_taxonomies) {
            $tax_query = [];
            $taxonomies_groups = [];
            
            // Raggruppa i termini per tassonomia
            foreach ($include_taxonomies as $term_slug) {
                $term = get_term_by('slug', $term_slug);
                if ($term) {
                    $taxonomies_groups[$term->taxonomy][] = $term->term_id;
                }
            }
            
            // Crea la tax_query per ogni tassonomia
            foreach ($taxonomies_groups as $taxonomy => $term_ids) {
                $tax_query[] = [
                    'taxonomy' => $taxonomy,
                    'field' => 'term_id',
                    'terms' => $term_ids,
                    'operator' => 'IN'
                ];
            }
            
            if (!empty($tax_query)) {
                $tax_query['relation'] = 'OR';
                $args['tax_query'] = $tax_query;
            }
        }
        
        // Compatibilità con vecchi nomi (exclude_tags) e nuovi (exclude_taxonomies)
        $exclude_taxonomies = $query_params->exclude_taxonomies ?? $query_params->exclude_tags ?? null;
        if ($exclude_taxonomies) {
            $exclude_tax_query = [];
            $exclude_taxonomies_groups = [];
            
            // Raggruppa i termini per tassonomia
            foreach ($exclude_taxonomies as $term_slug) {
                $term = get_term_by('slug', $term_slug);
                if ($term) {
                    $exclude_taxonomies_groups[$term->taxonomy][] = $term->term_id;
                }
            }
            
            // Crea la tax_query per escludere ogni tassonomia
            foreach ($exclude_taxonomies_groups as $taxonomy => $term_ids) {
                $exclude_tax_query[] = [
                    'taxonomy' => $taxonomy,
                    'field' => 'term_id',
                    'terms' => $term_ids,
                    'operator' => 'NOT IN'
                ];
            }
            
            if (!empty($exclude_tax_query)) {
                if (isset($args['tax_query'])) {
                    // Se esiste già una tax_query, combinala
                    $args['tax_query'] = [
                        'relation' => 'AND',
                        $args['tax_query'],
                        $exclude_tax_query
                    ];
                } else {
                    $exclude_tax_query['relation'] = 'AND';
                    $args['tax_query'] = $exclude_tax_query;
                }
            }
        }
        
        if (isset($query_params->post_types)) {
            $args['post_type'] = $query_params->post_types;
        }
        
        if (isset($query_params->meta_query)) {
            $args['meta_query'] = $query_params->meta_query;
        }
        
        if (isset($query_params->exclude_featured) && $query_params->exclude_featured) {
            $featured = $this->getGenericFeed('featured');
            if (!empty($featured)) {
                $args['post__not_in'] = [$featured[0]->id];
            }
        }
        
        $args = array_merge($args, $additional_args);
        $args = $this->excludeUsedPosts($args);
        
        return $args;
    }



    private function subject() { 
        $featured_posts = $this->getGenericFeed('featured');
        if (empty($featured_posts)) {
            return 'Newsletter - ' . get_bloginfo('name');
        }
        
        $featured_post = $featured_posts[0];
        $featured_subject = get_field('newsletter_subject', $featured_post->id);
        return ( empty( $featured_subject ) ) ? $featured_post->title : $featured_subject;
    }   
    
    private function summary() { 
        $featured_posts = $this->getGenericFeed('featured');
        if (empty($featured_posts)) {
            return '';
        }
        
        $featured_post = $featured_posts[0];
        $featured_subject = get_field('newsletter_summary', $featured_post->id);
        return ( empty( $featured_subject ) ) ? '' : $featured_subject;
    }

    // Metodo flag_as_sent rimosso - non più necessario

    private function getTemplatePosts( array $posts ) {
        $template_posts = array_map( function( $post ) {
            return $this->postTemplate( $post );   
        }, $posts );

        return array_values(
            array_filter( $template_posts, function ($post) { return $post != null; } ) 
        );
    }
    
    private function getTagIDS( string $tag = '') {
        $tag_sponsored       = get_term_by('slug', 'sponsored',       'post_tag');
        $tag_blind_sponsored = get_term_by('slug', 'blind-sponsored', 'post_tag');
        $tag_primeday        = get_term_by('slug', 'primeday',        'post_tag');
        $selected_tag        = $tag == '' ? null : get_term_by('slug', $tag, 'post_tag');
        $tag_nl_sponsored    = get_term_by('slug', 'nl_sponsored',    'post_tag');
        $tag_offerte         = get_term_by('slug', 'offerte',         'post_tag');
        
        return (object) [
            'sponsored'       =>  empty($tag_sponsored)       ? 0 : $tag_sponsored->term_id,
            'blind_sponsored' =>  empty($tag_blind_sponsored) ? 0 : $tag_blind_sponsored->term_id,
            'primeday'        =>  empty($tag_primeday)        ? 0 : $tag_primeday->term_id,
            'selected'        =>  empty($selected_tag)        ? 0 : $selected_tag->term_id,
            'nl_sponsored'    =>  empty($tag_nl_sponsored)    ? 0 : $tag_nl_sponsored->term_id,
            'tag_offerte'     =>  empty($tag_offerte)         ? 0 : $tag_offerte->term_id
        ];
    }

    private function postTemplate( $post ) {
        $tags = array_map( function( $tag ) {   return $tag->name;    }, wp_get_post_tags( $post->ID ) ) ;
        $link = in_array('blz_external', $tags) ? $this->getExternalLink( $post ) : get_permalink( $post->ID );
        
        if( empty($link) ) return null;

        $image_id  = get_post_thumbnail_id( $post->ID); 
        $image_url = ($image_id != 0) ? wp_get_attachment_image_src($image_id, 'image-card-medium')[0] : null;
        
        return (object) [
            'id'          => $post->ID,
            'title'       => apply_filters( 'the_title_rss', $post->post_title ),
            'date'        => mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true, $post->ID ), false ),
            'author'      => get_the_author_meta( 'display_name', $post->post_author),            
            'image'       => $image_url,
            'description' => get_the_excerpt( $post ),                  
            'link'        => $link,
        ];
    } 

    private function getExternalLink( $post ) {
        $external_link = get_post_meta ( $post->ID, 'external-permalink' )[0]; 
        if( !strpos($external_link, '?p=') && !strpos($external_link, '&p=') )
            return $external_link;
        else 
            return null;
    }
    
    private function getQueryBasicArgs() {
        $lastNewsletterDate = SiteConfig::getLastNewsletterDate();
        
        // Se non c'è data ultimo invio, usa ieri alle 00:00:00
        if (empty($lastNewsletterDate)) {
            $start_date = date('Y-m-d 00:00:00', strtotime('-1 day'));
        } else {
            // Se c'è data ultimo invio, usa quella data alle 00:00:00 (senza ora)
            $start_date = date('Y-m-d 00:00:00', strtotime($lastNewsletterDate));
        }
        
        // Data di fine: 00:00:00 del giorno corrente
        $end_date = date('Y-m-d 00:00:00');
        
    
        return [
            'post_status'    => 'publish',
            'post_type'      => [ 'post' ],
            'date_query'     => [
                [
                    'after' => $start_date,
                    'before' => $end_date,
                    'inclusive' => false // Esclude le date esatte
                ]
            ]
        ];
    }

    private function getRSS() { 
        ob_start();
        
        // Ottieni i post per questo feed
        $posts = $this->getGenericFeed($this->feed_type);
        
        echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>';
        ?>
        <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"
                   xmlns:wfw="http://wellformedweb.org/CommentAPI/" 
                   xmlns:dc="http://purl.org/dc/elements/1.1/" 
                   xmlns:media="http://search.yahoo.com/mrss/"
                   xmlns:atom="http://www.w3.org/2005/Atom"
                   xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
                   xmlns:slash="http://purl.org/rss/1.0/modules/slash/" 
                   <?php do_action('rss2_ns'); ?>>
            <channel>
                <title><?php bloginfo_rss('name'); ?> - Feed</title>
                <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
                <link><?php bloginfo_rss('url') ?></link>
                <description><?php bloginfo_rss('description') ?></description>
                <lastBuildDate><?= date('D, d M Y H:i:s +0000') ?></lastBuildDate>
                <language><?php echo get_option('rss_language'); ?></language>
                <sy:updatePeriod><?php echo apply_filters('rss_update_period', 'hourly'); ?></sy:updatePeriod>
                <sy:updateFrequency><?php echo apply_filters('rss_update_frequency', '1'); ?></sy:updateFrequency>
                <?php foreach( $posts as $item ) { 
                    $this->itemMarkup($item);
                } ?>                
            </channel>
        </rss>
        <?php 
        
        return ob_get_clean();
    }

    private function itemMarkup($item) { 
        $link = $item->link ?? '';
        // Aggiungi parametri UTM al link (gestisce correttamente link con parametri esistenti)
        if (!empty($link)) {
            $separator = strpos($link, '?') !== false ? '&' : '?';
            $link = $link . $separator . 'utm_source=newsletter&utm_medium=email';
        }
        ?><item>
            <title><?=$item->title?></title>
            <link><?= esc_url($link) ?></link>
            <pubDate><?=$item->date ?></pubDate>
            <?php if ( !empty( $item->image ) ) : ?>
                <media:content url="<?=$item->image ?>" type="image/jpeg" /> 
            <?php endif; ?>
            <dc:creator><?=$item->author; ?></dc:creator>                    
            <description><![CDATA[<?=$item->description ?>]]></description>
            <?php rss_enclosure(); ?>            
        </item><?php 
    }
       
    // Metodo flagAsSent rimosso - non più necessario
}
