<?php

namespace Database\Seeders;

use App\Helpers\FirstParty\AI\CloudflareAI;
use App\Models\Category;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;

class CategorySeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        // Path to the JSON files
        $jsonPath = database_path('seeders/data/json/category');

        // Check if directory exists
        if (! File::exists($jsonPath)) {
            $this->command->error("JSON directory not found: {$jsonPath}");

            return;
        }

        // Get all JSON files except the schema file
        $jsonFiles = File::glob($jsonPath.'/*.json');
        $jsonFiles = array_filter($jsonFiles, function ($file) {
            return ! str_contains(basename($file), 'schema');
        });

        $this->command->info('Starting to seed categories from JSON files...');
        $this->command->info('Found '.count($jsonFiles).' JSON files to process.');

        foreach ($jsonFiles as $jsonFile) {
            $this->processJsonFile($jsonFile);
        }

        $this->command->info('Category seeding completed successfully!');
    }

    /**
     * Process a single JSON file
     */
    private function processJsonFile(string $filePath): void
    {
        $fileName = basename($filePath);
        $this->command->info("Processing: {$fileName}");

        try {
            // Read and decode JSON content
            $jsonContent = File::get($filePath);
            $data = json_decode($jsonContent, true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                $this->command->error("Invalid JSON in file: {$fileName} - ".json_last_error_msg());

                return;
            }

            // Validate JSON structure
            if (! isset($data['category'])) {
                $this->command->error("Missing 'category' key in file: {$fileName}");

                return;
            }

            $categoryData = $data['category'];

            // Validate required fields
            if (! isset($categoryData['name']) || ! isset($categoryData['description'])) {
                $this->command->error("Missing required fields (name/description) in file: {$fileName}");

                return;
            }

            // Create main category
            $mainCategory = $this->createMainCategory($categoryData, $data);

            if (! $mainCategory) {
                $this->command->error("Failed to create main category for file: {$fileName}");

                return;
            }

            // Create subcategories
            if (isset($categoryData['subcategories']) && is_array($categoryData['subcategories'])) {
                foreach ($categoryData['subcategories'] as $index => $subcategoryData) {
                    if (! $this->createSubcategory($subcategoryData, $mainCategory, $data, $index)) {
                        $this->command->warn("Failed to create subcategory at index {$index} for file: {$fileName}");
                    }
                }
            }

            $this->command->info("✓ Successfully processed: {$fileName}");
        } catch (\Exception $e) {
            $this->command->error("Error processing {$fileName}: ".$e->getMessage());
            Log::error("CategorySeeder error for {$fileName}", [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
        }
    }

    /**
     * Create a main category
     */
    private function createMainCategory(array $categoryData, array $originalData): ?Category
    {
        try {
            // Check if category already exists
            $existingCategory = Category::where('name', $categoryData['name'])
                ->whereNull('parent_id')
                ->first();

            if ($existingCategory) {
                $this->command->warn("Main category '{$categoryData['name']}' already exists. Skipping...");

                return $existingCategory;
            }

            // Create the main category
            $category = Category::create([
                'is_enabled' => true,
                'name' => $categoryData['name'],
                'description' => $categoryData['description'],
                'subcategories' => $categoryData['subcategories'] ?? null,
                'keywords' => $categoryData['keywords'] ?? null,
                'meme_angles' => null, // Main categories don't have meme_angles
                'sample_captions' => null, // Main categories don't have sample_captions
                'payload' => $originalData,
                'embedding' => CloudflareAI::getVectorEmbeddingBgeSmall($categoryData['name'].' '.$categoryData['description']),
            ]);

            // Add keywords as tags
            if (isset($categoryData['keywords']) && is_array($categoryData['keywords'])) {
                $this->attachKeywordsAsTags($category, $categoryData['keywords']);
            }

            $this->command->line("  ✓ Created main category: {$category->name}");

            return $category;
        } catch (\Exception $e) {
            $this->command->error('Error creating main category: '.$e->getMessage());
            Log::error('Error creating main category', [
                'category_data' => $categoryData,
                'error' => $e->getMessage(),
            ]);

            return null;
        }
    }

    /**
     * Create a subcategory
     */
    private function createSubcategory(array $subcategoryData, Category $parentCategory, array $originalData, int $index): ?Category
    {
        try {
            // Validate required subcategory fields
            if (! isset($subcategoryData['name']) || ! isset($subcategoryData['description'])) {
                $this->command->warn("Subcategory at index {$index} missing required fields (name/description). Skipping...");

                return null;
            }

            // Check if subcategory already exists
            $existingSubcategory = Category::where('name', $subcategoryData['name'])
                ->where('parent_id', $parentCategory->id)
                ->first();

            if ($existingSubcategory) {
                $this->command->warn("    Subcategory '{$subcategoryData['name']}' already exists. Skipping...");

                return $existingSubcategory;
            }

            // Create subcategory payload
            $subcategoryPayload = [
                'subcategory' => $subcategoryData,
                'parent_category' => [
                    'name' => $parentCategory->name,
                    'description' => $parentCategory->description,
                ],
            ];

            // Create the subcategory using the correct nested set method
            $subcategory = Category::create([
                'is_enabled' => false,
                'name' => $subcategoryData['name'],
                'description' => $subcategoryData['description'],
                'meme_angles' => $subcategoryData['meme_angles'] ?? null,
                'sample_captions' => $subcategoryData['sample_captions'] ?? null,
                'keywords' => $subcategoryData['keywords'] ?? null,
                'subcategories' => null, // Subcategories don't have subcategories
                'payload' => $subcategoryPayload,
                'parent_id' => $parentCategory->id, // Set parent_id directly
                'embedding' => CloudflareAI::getVectorEmbeddingBgeSmall($subcategoryData['name'].' '.$subcategoryData['description']),
            ]);

            // Add keywords as tags
            if (isset($subcategoryData['keywords']) && is_array($subcategoryData['keywords'])) {
                $this->attachKeywordsAsTags($subcategory, $subcategoryData['keywords']);
            }

            $this->command->line("    ✓ Created subcategory: {$subcategory->name}");

            return $subcategory;
        } catch (\Exception $e) {
            $this->command->error("Error creating subcategory at index {$index}: ".$e->getMessage());
            Log::error('Error creating subcategory', [
                'subcategory_data' => $subcategoryData,
                'parent_id' => $parentCategory->id,
                'error' => $e->getMessage(),
            ]);

            return null;
        }
    }

    /**
     * Attach keywords as tags to a category
     */
    private function attachKeywordsAsTags(Category $category, array $keywords): void
    {
        try {
            $category->attachTags($keywords, 'category');
        } catch (\Exception $e) {
            $this->command->warn("Failed to attach tags to category '{$category->name}': ".$e->getMessage());
            Log::warning('Failed to attach tags', [
                'category_id' => $category->id,
                'keywords' => $keywords,
                'error' => $e->getMessage(),
            ]);
        }
    }
}
