<?php

namespace App\Services\Admin;

use App\Models\Post;
use App\Models\RssFeed;
use App\Models\Category;
use App\Services\AiService;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Log;
use fivefilters\Readability\Readability;
use fivefilters\Readability\Configuration;

class RssCrawlerService
{
    protected $aiService;

    // --- 1. DEFAULT PROFESSIONAL PROMPT (Fallback) ---
    // This is used if the user did not enter a custom prompt in the RSS settings.
    protected $defaultPrompt = <<<EOT
You are a senior news editor for a top-tier media outlet. Your task is to rewrite the provided content into a unique, high-quality news report.

**Guidelines for Writing:**
1. **Tone:** Professional, objective, and clear. Write like a human journalist, not a robot. Avoid clichés like "In conclusion" or "Furthermore".
2. **Structure:** Use **short, punchy paragraphs** (2-3 sentences max). This is critical for readability.
3. **Language:** Use simple, accessible English. Avoid overly complex vocabulary or childish excitement.
4. **Accuracy:** Keep all names, dates, quotes, and key facts exactly as they appear. Do not invent information.
5. **Clean Up:** Remove any "Read more" links, promotional text, or social media calls to action.

**Output Format:** 
Return the content as clean HTML using only <p> tags.
EOT;

    // Browser User Agents to rotate
    protected $userAgents =[
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0',
    ];

    public function __construct(AiService $aiService)
    {
        $this->aiService = $aiService;
    }

    public function run(RssFeed $feed)
    {
        // 0. PRE-FETCH CATEGORIES (Optimization)
        $categoryListString = "";
        $validCategoryIds = collect();

        if ($feed->is_auto_category_enabled) {
            $categories = Category::select('id', 'name')->get();
            $validCategoryIds = $categories->pluck('id');
            
            $categoryListString = $categories->map(function($c) {
                return "- ID {$c->id}: {$c->name}";
            })->implode("\n");
        }

        try {
            // 1. Fetch RSS XML
            $response = Http::withHeaders($this->getRealBrowserHeaders())
                ->timeout(30)
                ->withoutVerifying() 
                ->get($feed->feed_url);
            
            if ($response->failed()) {
                throw new \Exception("Failed to fetch RSS URL: {$feed->feed_url} (Status: {$response->status()})");
            }

            $rssContent = $response->body();
            
            libxml_use_internal_errors(true);
            $xml = simplexml_load_string($rssContent, 'SimpleXMLElement', LIBXML_NOCDATA);
            
            if (!$xml) {
                $errors = libxml_get_errors();
                libxml_clear_errors();
                throw new \Exception("Invalid XML format: " . ($errors[0]->message ?? 'Unknown error'));
            }

            $items = isset($xml->channel->item) ? $xml->channel->item : (isset($xml->entry) ? $xml->entry :[]);
            
            $savedCount = 0;

            foreach ($items as $item) {
                if ($savedCount >= $feed->posts_limit_per_crawl) {
                    break; 
                }

                $title = (string) $item->title;
                $link = isset($item->link['href']) ? (string) $item->link['href'] : (string) $item->link;
                $description = isset($item->description) ? (string) $item->description : ((string) $item->summary ?? '');

                if (Post::where('source_url', $link)->exists()) continue; 
                if (!$this->passesKeywords($title, $description, $feed)) continue;

                try {
                    sleep(rand(1, 3));
                    $postData = $this->processItem($item, $link, $description, $feed);
                } catch (\Exception $e) {
                    Log::warning("Skipping item '{$title}' due to processing error: " . $e->getMessage());
                    continue;
                }

                if ($postData && !empty(strip_tags($postData['content']))) {
                    
                    $finalContent = $postData['content'];
                    $finalTitle = Str::limit($title, 250);
                    $finalCategoryId = $feed->category_id; 

                    // --- AI REWRITE & AUTO-CATEGORY LOGIC ---
                    if ($feed->is_rewrite_enabled) {
                        try {
                            // 2. DETERMINE PROMPT (Use Custom or Default)
                            $basePrompt = !empty($feed->rewrite_prompt) ? $feed->rewrite_prompt : $this->defaultPrompt;
                            
                            $fullPrompt = $basePrompt;

                            // Inject Auto-Category Instructions
                            if ($feed->is_auto_category_enabled) {
                                $fullPrompt .= "\n\n" .
                                    "*** AUTO-CATEGORIZATION TASK ***\n" .
                                    "Analyze the content and select the most appropriate Category ID from this list:\n" .
                                    $categoryListString . "\n" .
                                    "Current Default ID: {$feed->category_id}\n\n" .
                                    "INSTRUCTIONS:\n" .
                                    "1. If the article fits a specific category from the list better than the default, use that ID.\n" .
                                    "2. If unsure, use the default ID.\n" .
                                    "3. Your JSON response MUST include a 'category_id' (integer) field along with 'title' and 'content'.\n";
                            }

                            $rewrittenResult = $this->aiService->rewrite($finalContent, $fullPrompt);
                            
                            if ($rewrittenResult === null) {
                                Log::warning("AI Rewrite returned null for '{$title}'. Skipping post.");
                                continue; // Skip post if AI fails to return data
                            }
                            else if (is_array($rewrittenResult) && isset($rewrittenResult['skip']) && $rewrittenResult['skip'] === true) {
                                Log::info("AI rejected content for '{$title}'. Reason: " . ($rewrittenResult['reason'] ?? 'Unknown') . ". Skipping post.");
                                continue; // Skip post if AI says it's garbage/too short
                            }
                            else if (is_array($rewrittenResult)) {
                                if (!empty($rewrittenResult['title'])) {
                                    $finalTitle = Str::limit($rewrittenResult['title'], 250);
                                }
                                if (!empty($rewrittenResult['content'])) {
                                    $finalContent = $rewrittenResult['content'];
                                }

                                if ($feed->is_auto_category_enabled && !empty($rewrittenResult['category_id'])) {
                                    $suggestedId = intval($rewrittenResult['category_id']);
                                    if ($validCategoryIds->contains($suggestedId)) {
                                        $finalCategoryId = $suggestedId;
                                    }
                                }
                            } 
                            else if (is_string($rewrittenResult) && !empty($rewrittenResult)) {
                                $finalContent = $rewrittenResult;
                            }
                            
                        } catch (\Exception $e) {
                            Log::error("RSS AI Rewrite Failed for '{$title}'. Post skipped. Error: " . $e->getMessage());
                            continue; 
                        }
                    }

                    Post::create([
                        'user_id' => $feed->user_id,
                        'category_id' => $finalCategoryId,
                        'rss_feed_id' => $feed->id,
                        'title' => $finalTitle,
                        'slug' => Post::generateUniqueSlug($finalTitle), 
                        'meta_description' => Str::limit(strip_tags($finalContent), 155),
                        'content' => $finalContent,
                        'image_path' => $postData['image'],
                        'source_url' => $link,
                        'status' => $feed->status_on_import,
                        'tags' =>[],
                        'views_count' => 0
                    ]);

                    $savedCount++;
                }
            }

            $feed->update(['last_crawled_at' => now()]);

        } catch (\Exception $e) {
            Log::error("Crawler Error [Feed ID: {$feed->id}]: " . $e->getMessage());
            throw $e; 
        }
    }

    private function getRealBrowserHeaders()
    {
        return [
            'User-Agent' => $this->userAgents[array_rand($this->userAgents)],
            'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language' => 'en-US,en;q=0.9',
            'Accept-Encoding' => 'gzip, deflate, br',
            'Connection' => 'keep-alive',
            'Upgrade-Insecure-Requests' => '1',
            'Cache-Control' => 'max-age=0',
            'Referer' => 'https://www.google.com/',
        ];
    }

    private function passesKeywords($title, $desc, RssFeed $feed)
    {
        $text = strtolower($title . ' ' . $desc);

        if (!empty($feed->must_contain_keywords)) {
            $found = false;
            foreach ($feed->must_contain_keywords as $keyword) {
                if (trim($keyword) === '') continue;
                if (str_contains($text, strtolower(trim($keyword)))) {
                    $found = true;
                    break;
                }
            }
            if (!$found) return false;
        }

        if (!empty($feed->must_not_contain_keywords)) {
            foreach ($feed->must_not_contain_keywords as $keyword) {
                if (trim($keyword) === '') continue;
                if (str_contains($text, strtolower(trim($keyword)))) {
                    return false;
                }
            }
        }

        return true;
    }

    private function processItem($item, $link, $description, RssFeed $feed)
    {
        $content = $description; 
        $image = null;

        $namespaces = $item->getNamespaces(true);
        if (isset($namespaces['media'])) {
            $media = $item->children($namespaces['media']);
            if (isset($media->content)) $image = (string) $media->content->attributes()['url'];
            elseif (isset($media->thumbnail)) $image = (string) $media->thumbnail->attributes()['url'];
        }
        if (!$image && isset($item->enclosure) && str_contains((string)$item->enclosure->attributes()['type'], 'image')) {
            $image = (string)$item->enclosure->attributes()['url'];
        }
        if (!$image && preg_match('/<img[^>]+src="([^">]+)"/', $description, $matches)) {
            $image = $matches[1];
        }

        if ($feed->fetch_full_content) {
            try {
                $response = Http::withHeaders($this->getRealBrowserHeaders())
                    ->timeout(15)
                    ->withoutVerifying()
                    ->get($link);

                if ($response->successful()) {
                    $html = $response->body();
                    
                    $configuration = new Configuration();
                    $configuration->setFixRelativeUrls(true);
                    $configuration->setOriginalUrl($link); 
                    
                    $readability = new Readability($configuration);
                    
                    if ($readability->parse($html)) {
                        $cleanContent = (string) $readability->getContent(); 
                        
                        if (!$image) {
                            $scrapedImage = $readability->getImage(); 
                            if ($scrapedImage) {
                                $image = $scrapedImage;
                            }
                        }

                        if (strlen(strip_tags($cleanContent)) > 100) {
                            $content = $cleanContent;
                        }
                    }
                }
            } catch (\Exception $e) {
                Log::warning("Scrape failed for {$link}: " . $e->getMessage());
            }
        }

        if ($image && !Str::startsWith($image, ['http', '//'])) {
            $image = rtrim($link, '/') . '/' . ltrim($image, '/');
        }

        return[
            'description' => $description,
            'content' => $content ?: $description, 
            'image' => $image
        ];
    }
}