<?php

namespace NewsletterBridge\Services\Newsletter;

use NewsletterBridge\Interfaces\NewsletterOrchestratorInterface;
use NewsletterBridge\Services\Feed\XMLGenerationService;
use NewsletterBridge\Services\Newsletter\NewsletterSendingService;
use NewsletterBridge\Services\Newsletter\NewsletterFeed;

/**
 * Responsabilità: Orchestrazione processo newsletter
 * Single Responsibility: Solo orchestrazione del processo
 * Refactored: Usa composizione per separare responsabilità
 */
class NewsletterOrchestrator implements NewsletterOrchestratorInterface {
    
    private XMLGenerationService $xmlGenerationService;
    private NewsletterSendingService $sendingService;
    private NewsletterFeed $nlFeed;
    
    public function __construct(
        XMLGenerationService $xmlGenerationService,
        NewsletterSendingService $sendingService,
        NewsletterFeed $nlFeed
    ) {
        $this->xmlGenerationService = $xmlGenerationService;
        $this->sendingService = $sendingService;
        $this->nlFeed = $nlFeed;
    }
    
    /**
     * Genera i file XML per la newsletter
     */
    public function generateXML(\stdClass $config, bool $generateFiles = true, string $subject = '', string $summary = '', int $site_id = null): array {
        $allFeeds = $this->xmlGenerationService->generateXML($config, $generateFiles, $site_id);
        
        // Soggetto: sempre da configurazione "Titolo Newsletter" con sostituzione {{date}}
        if (!$subject) {
            $title = $config->newsletter_title ?? 'Newsletter {{date}}';
            $subject = $this->replaceDatePlaceholder($title);
        }
        // Summary: lasciato vuoto salvo valore esplicito
        $summary = $summary ?: '';
        
        return $allFeeds;
    }
    
    /**
     * Estrae il titolo dal feed XML
     */
    private function extractTitleFromFeed(string $feedXml, \stdClass $config): string {
        // Cerca il tag <title> nel feed XML
        if (preg_match('/<title>(.*?)<\/title>/s', $feedXml, $matches)) {
            return trim(strip_tags($matches[1]));
        }
        
        // Fallback: cerca nel primo item
        if (preg_match('/<item>.*?<title>(.*?)<\/title>.*?<\/item>/s', $feedXml, $matches)) {
            return trim(strip_tags($matches[1]));
        }
        
        // Fallback finale: usa il titolo dalla configurazione
        $title = $config->newsletter_title ?? 'Newsletter {{date}}';
        
        // Sostituisce il placeholder {{date}} con la data italiana
        $title = $this->replaceDatePlaceholder($title);
        
        return $title;
    }
    
    /**
     * Sostituisce il placeholder {{date}} con la data italiana
     */
    private function replaceDatePlaceholder(string $title): string {
        if (strpos($title, '{{date}}') === false) {
            return $title;
        }

        $now = new \DateTimeImmutable('now', new \DateTimeZone('Europe/Rome'));
        $months = [
            '01' => 'gennaio',
            '02' => 'febbraio',
            '03' => 'marzo',
            '04' => 'aprile',
            '05' => 'maggio',
            '06' => 'giugno',
            '07' => 'luglio',
            '08' => 'agosto',
            '09' => 'settembre',
            '10' => 'ottobre',
            '11' => 'novembre',
            '12' => 'dicembre',
        ];

        $day = (int) $now->format('j');
        $monthKey = $now->format('m');
        $monthName = $months[$monthKey] ?? $now->format('F');
        $year = $now->format('Y');

        $italianDate = sprintf('%d %s %s', $day, $monthName, $year);

        return str_replace('{{date}}', $italianDate, $title);
    }
    
    /**
     * Invia la newsletter completa
     */
    public function sendNewsletter(\stdClass $config, bool $dryrun = false, int $site_id = null, bool $force = false): bool {
        // Controlla se la newsletter è già stata inviata oggi (solo se non è force)
        if (!$force && !$this->canSendToday($site_id)) {
            $error_message = 'Newsletter già inviata oggi. Usa --force per forzare l\'invio.';
            \WP_CLI::warning('⚠️  ' . $error_message);
            throw new \Exception($error_message);
        }
        
        // Controlla se i feed sono vuoti
        if (!$this->hasValidFeeds($config, $site_id)) {
            $error_message = 'Impossibile inviare: tutti i feed sono vuoti. Verificare la configurazione dei feed.';
            \WP_CLI::error('❌ ' . $error_message);
            throw new \Exception($error_message);
        }
        
        // Genera i file XML e ottieni subject/summary
        $allFeeds = $this->generateXML($config, true, '', '', $site_id);
        
        // Soggetto: sempre da configurazione
        // Se viene passato site_id, ricarica la configurazione dal contesto corrente per avere il titolo corretto
        if ($site_id !== null) {
            $current_blog_id = function_exists('get_current_blog_id') ? get_current_blog_id() : null;
            if ($current_blog_id === $site_id) {
                // Il contesto è già stato cambiato, ricarica la configurazione dal contesto corrente
                $current_config = get_newsletter_config();
                $title = $current_config->newsletter_title ?? 'Newsletter {{date}}';
            } else {
                // Il contesto non è stato cambiato, usa la configurazione passata
                $title = $config->newsletter_title ?? 'Newsletter {{date}}';
            }
        } else {
            // Nessun site_id, usa la configurazione passata
            $title = $config->newsletter_title ?? 'Newsletter {{date}}';
        }
        
        $subject = $this->replaceDatePlaceholder($title);
        $summary = '';
        
        // Invia la newsletter (passa site_id per il contesto multisite)
        return $this->sendingService->sendNewsletter($dryrun, $subject, $summary, $site_id);
    }
    
    /**
     * Verifica se i feed contengono contenuti validi
     */
    private function hasValidFeeds(\stdClass $config, int $site_id = null): bool {
        // Resetta i post utilizzati per il controllo
        $container = new \NewsletterBridge\Utils\ServiceContainer();
        $container->configureDefaultServices();
        $feedGenerator = $container->get('feed_generator');
        $feedGenerator->resetUsedPosts();
        
        // Genera i feed senza salvare i post utilizzati, passando site_id
        $allFeeds = $this->xmlGenerationService->generateXML($config, false, $site_id);
        
        foreach ($allFeeds as $feedType => $feedContent) {
            if ($feedType === 'subject') {
                continue;
            }
            
            // Verifica se il feed contiene almeno un item
            if (strpos($feedContent, '<item>') !== false) {
                \WP_CLI::log("✓ Feed {$feedType} contiene contenuti validi");
                return true;
            }
        }
        
        \WP_CLI::log("❌ Tutti i feed sono vuoti (nessun <item> trovato)");
        return false;
    }
    
    /**
     * Verifica se può inviare oggi (controlla calendario e data ultimo invio)
     */
    private function canSendToday(int $site_id = null): bool {
        // Se viene passato site_id, verifica se il contesto corrente corrisponde
        // Se corrisponde, usa get_newsletter_config() senza parametri per usare il contesto corrente
        // Altrimenti, passa site_id per leggere le opzioni del sito specifico
        $current_blog_id = function_exists('get_current_blog_id') ? get_current_blog_id() : null;
        if ($site_id !== null && $current_blog_id === $site_id) {
            // Il contesto è già stato cambiato, usa il contesto corrente
            $config = get_newsletter_config();
        } else {
            // Usa get_newsletter_config() con site_id per leggere le opzioni del sito specifico
            $config = get_newsletter_config($site_id);
        }
        
        // Controlla il calendario
        $calendarChecker = new \NewsletterBridge\Services\Content\CalendarChecker($config);
        $calendarResult = $calendarChecker->checkDate();
        if ($calendarResult !== 'ok') {
            $error_message = 'Oggi non è un giorno inviabile secondo il calendario: ' . $calendarResult;
            \WP_CLI::warning('⚠️  ' . $error_message);
            throw new \Exception($error_message);
        }
        
        // Controlla se è già stata inviata oggi
        $lastSent = \NewsletterBridge\Config\SiteConfig::getLastNewsletterDate();
        if ($lastSent && $lastSent === date('Y-m-d')) {
            $error_message = 'Newsletter già inviata oggi (' . $lastSent . ')';
            throw new \Exception($error_message);
        }
        
        return true;
    }
}
