<?php

namespace App\Console\Commands;

use App\Models\Category;
use App\Models\Product;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

class ImportMecaprogramsProducts extends Command
{
    protected $signature = 'mecaprograms:import-products
        {--category= : Import only specific category slug}
        {--limit= : Max products to import}
        {--delay=300 : Milliseconds between requests}
        {--dry-run : Print what would be imported without saving}';

    protected $description = 'Import products from mecaprograms.com via sitemap';

    protected array $categoryMap = [
        'transmision' => 'transmission',
        'trucks&heavy-trucks' => 'truck-heavy-truck',
    ];

    protected string $baseUrl = 'https://mecaprograms.com';

    protected int $imported = 0;
    protected int $skipped = 0;
    protected int $failed = 0;

    public function handle(): int
    {
        ini_set('memory_limit', '512M');
        $this->info('Fetching sitemap to discover product URLs...');

        $productUrls = $this->fetchSitemapProducts();
        $this->info("Found " . count($productUrls) . " product URLs in sitemap");

        $limit = (int) ($this->option('limit') ?: count($productUrls));
        $productUrls = array_slice($productUrls, 0, $limit);

        $existingSlugs = Product::pluck('slug')->toArray();
        $productUrls = array_filter($productUrls, function ($url) use ($existingSlugs) {
            return !in_array($this->extractSlug($url), $existingSlugs);
        });

        $totalNew = count($productUrls);
        if ($totalNew === 0) {
            $this->info('All products already imported.');
            return Command::SUCCESS;
        }

        $this->info("Processing {$totalNew} new products...");

        $filterCategory = $this->option('category');

        foreach ($productUrls as $url) {
            $slug = $this->extractSlug($url);

            if ($this->option('dry-run')) {
                $this->line("Would fetch: {$url}");
                $this->imported++;
                continue;
            }

            $this->scrapeProduct($slug, $filterCategory);

            if (gc_enabled()) {
                gc_collect_cycles();
            }
            usleep((int) $this->option('delay') * 1000);
        }

        if ($this->option('dry-run')) {
            $this->newLine();
            $this->info("Dry run complete. {$this->imported} products would be processed.");
        } else {
            $this->newLine();
            $this->table(
                ['Imported', 'Skipped', 'Failed'],
                [[$this->imported, $this->skipped, $this->failed]]
            );
        }

        return Command::SUCCESS;
    }

    protected function fetchSitemapProducts(): array
    {
        $response = Http::withOptions(['verify' => false])
            ->withHeaders(['User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'])
            ->timeout(30)
            ->get("{$this->baseUrl}/sitemap.xml");

        if (!$response->successful()) {
            $this->error("Failed to fetch sitemap (HTTP {$response->status()})");
            return [];
        }

        preg_match_all(
            '!https://mecaprograms\.com/software/[^<]+!',
            html_entity_decode($response->body()),
            $matches
        );

        return $matches[0] ?? [];
    }

    protected function extractSlug(string $url): string
    {
        return basename(parse_url($url, PHP_URL_PATH));
    }

    protected function scrapeProduct(string $slug, ?string $filterCategory): void
    {
        $url = "{$this->baseUrl}/software/{$slug}";
        $this->line("  Fetching: {$url}");

        $this->line("  Fetching: {$url}");

        try {
            $response = Http::withOptions(['verify' => false])
                ->withHeaders([
                    'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                    'Accept' => 'text/html',
                ])->timeout(30)->get($url);

            if (!$response->successful()) {
                $this->warn("  Failed (HTTP {$response->status()})");
                $this->failed++;
                return;
            }

            $html = $response->body();
            $data = $this->parseProductPage($html, $slug);

            if (!$data) {
                $this->warn("  Could not parse product data for: {$slug}");
                $this->failed++;
                return;
            }

            if ($filterCategory && $data['category_slug'] !== $filterCategory) {
                $this->line("  Skipped (category filter): {$data['name']}");
                $this->skipped++;
                return;
            }

            $this->importProduct($data);

        } catch (\Exception $e) {
            $this->error("  Error: {$e->getMessage()}");
            $this->failed++;
        }
    }

    protected function parseProductPage(string $html, string $slug): ?array
    {
        $name = null;
        $price = null;
        $description = null;
        $categorySlug = null;

        if (preg_match('/<h1[^>]*class="[^"]*content-product-detail-info-title[^"]*"[^>]*>\s*([^<]+)/i', $html, $m)) {
            $name = trim(html_entity_decode(strip_tags($m[1])));
        }

        if (!$name) {
            if (preg_match('/<p[^>]*class="[^"]*content-product-detail-info-title-mb[^"]*"[^>]*>\s*([^<]+)/i', $html, $m)) {
                $name = trim(html_entity_decode(strip_tags($m[1])));
            }
        }

        if (!$name) {
            if (preg_match('/<title>([^<]+)\s*\|/i', $html, $m)) {
                $name = trim($m[1]);
            }
        }

        if (preg_match('/<p[^>]*class="[^"]*price-details[^"]*"[^>]*>\s*USD\s*([\d,]+\.?\d*)/i', $html, $m)) {
            $price = (float) str_replace(',', '', $m[1]);
        }

        if (preg_match('/<th[^>]*class="[^"]*informattion-of-characteristics[^"]*"[^>]*>\s*<span[^>]*class="[^"]*normal-case[^"]*"[^>]*>([\s\S]*?)<\/span>/i', $html, $m)) {
            $description = trim(strip_tags($m[1]));
        }

        if ($description === '' || $description === null) {
            if (preg_match('/<th[^>]*class="[^"]*title-of-characteristics[^"]*"[^>]*>\s*Description\s*<\/th>\s*<th[^>]*class="[^"]*informattion-of-characteristics[^"]*"[^>]*>([\s\S]*?)<\/th>/i', $html, $m)) {
                $description = trim(strip_tags($m[1]));
            }
        }

        $categoryFromBreadcrumb = null;
        if (preg_match('#<nav[^>]*aria-label="Breadcrumb"[^>]*>.*?<a[^>]*href="[^"]*/shop/category/([^"&]+)[^"]*"[^>]*>([^<]+)</a>#is', $html, $m)) {
            $categoryFromBreadcrumb = $m[1];
        }

        $categoryFromTable = null;
        if (preg_match('/<th[^>]*class="[^"]*title-of-characteristics[^"]*"[^>]*>\s*Category\s*<\/th>\s*<th[^>]*class="[^"]*informattion-of-characteristics[^"]*"[^>]*>([^<]+)<\/th>/i', $html, $m)) {
            $categoryFromTable = trim(strtolower($m[1]));
        }

        $categorySlug = $categoryFromBreadcrumb ?: $categoryFromTable;

        if (!$name) {
            return null;
        }

        $localCategorySlug = $this->categoryMap[$categorySlug] ?? $categorySlug;

        $name = $this->cleanProductName($name);

        return [
            'slug' => $slug,
            'name' => $name,
            'price' => $price ?? 0,
            'description' => $description,
            'category_slug' => $localCategorySlug,
        ];
    }

    protected function cleanProductName(string $name): string
    {
        $parts = explode("\n", $name);
        $name = trim($parts[0]);
        $name = preg_replace('/\s+[\d.]+(?:v[\d.]+)?\s*\[\d{4}\.\d{2}\]$/', '', $name);
        return $name;
    }

    protected function importProduct(array $data): void
    {
        $category = Category::where('slug', $data['category_slug'])->first();

        if (!$category) {
            $this->warn("  Category not found: {$data['category_slug']} for {$data['name']}");
            $this->failed++;
            return;
        }

        $existing = Product::where('slug', $data['slug'])->first();

        if ($existing) {
            $this->line("  Skipped (exists): {$data['name']} (\${$data['price']}) [{$category->name}]");
            $this->skipped++;
            return;
        }

        if ($this->option('dry-run')) {
            $this->line("  Would import: {$data['name']} (\${$data['price']}) [{$category->name}]");
            $this->imported++;
            return;
        }

        try {
            Product::create([
                'name' => $data['name'],
                'slug' => $data['slug'],
                'description' => $data['description'] ?: "Diagnostic software: {$data['name']}",
                'short_description' => Str::limit($data['description'] ?: "Professional diagnostic software for {$category->name}", 200),
                'price' => $data['price'],
                'sku' => strtoupper($data['slug']),
                'stock' => 999,
                'category_id' => $category->id,
                'is_featured' => false,
                'is_active' => true,
                'meta_title' => $data['name'],
                'meta_description' => Str::limit($data['description'] ?: "Buy {$data['name']} - diagnostic software for {$category->name}", 160),
            ]);

            $this->line("  Imported: {$data['name']} (\${$data['price']}) [{$category->name}]");
            $this->imported++;

        } catch (\Exception $e) {
            $this->error("  Failed to import {$data['name']}: {$e->getMessage()}");
            $this->failed++;
        }
    }
}
