<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\ProductRequest;
use App\Models\Category;
use App\Models\Product;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class AdminProductController extends Controller
{
    public function index(Request $request): View
    {
        $query = Product::with('category');

        if ($request->filled('search')) {
            $query->search($request->search);
        }

        if ($request->filled('category')) {
            $query->filterByCategory($request->category);
        }

        if ($request->filled('source')) {
            $query->where('source', $request->source);
        }

        if ($request->filled('min_price') || $request->filled('max_price')) {
            $query->filterByPriceRange($request->min_price, $request->max_price);
        }

        $products = $query->latest()->paginate(20);
        $categories = Category::orderBy('name_en')->get();

        return view('admin.products.index', compact('products', 'categories'));
    }

    public function create(): View
    {
        $categories = Category::orderBy('name_en')->get();

        return view('admin.products.create', compact('categories'));
    }

    public function store(ProductRequest $request): RedirectResponse
    {
        Product::create($request->validated());

        return redirect()->route('admin.products.index')
            ->with('success', 'Product created successfully.');
    }

    public function show(Product $product): View
    {
        $product->load('category');

        return view('admin.products.show', compact('product'));
    }

    public function edit(Product $product): View
    {
        $categories = Category::orderBy('name_en')->get();

        return view('admin.products.edit', compact('product', 'categories'));
    }

    public function update(ProductRequest $request, Product $product): RedirectResponse
    {
        $product->update($request->validated());

        return redirect()->route('admin.products.index')
            ->with('success', 'Product updated successfully.');
    }

    public function destroy(Product $product): RedirectResponse
    {
        $product->delete();

        return redirect()->route('admin.products.index')
            ->with('success', 'Product deleted successfully.');
    }

    public function import(): View
    {
        return view('admin.products.import');
    }

    public function getExistingProductIds(): JsonResponse
    {
        $productIds = Product::query()
            ->whereNotNull('product_id')
            ->pluck('product_id')
            ->map(fn ($id) => (string) $id)
            ->unique()
            ->values()
            ->toArray();

        return response()->json([
            'product_ids' => $productIds,
        ]);
    }

    public function storeImport(Request $request): JsonResponse
    {
        $request->validate([
            'category_id' => ['required', 'exists:categories,id'],
            'source' => ['required', 'in:aliexpress,amazon,noon'],
            'products' => ['required', 'array'],
            'language' => ['nullable', 'in:arabic,english'],
        ]);

        $categoryId = $request->category_id;
        $source = $request->source;
        $language = $request->input('language', 'arabic');
        $existingProductIds = $request->input('existing_product_ids', []);

        $imported = 0;
        $updated = 0;
        $failed = 0;
        $createdIds = [];

        foreach ($request->products as $rawProduct) {
            try {
                $productId = $rawProduct['ProductId'] ?? null;

                // Parse product data based on language
                $productData = $this->parseProductData(
                    $rawProduct,
                    $categoryId,
                    $source,
                    $language
                );

                // Smart detection: check if product exists by product_id
                if ($productId) {
                    $existingProduct = Product::where('product_id', $productId)->first();

                    if ($existingProduct) {
                        // Update existing product - only update language-specific fields
                        $updateData = $this->getLanguageSpecificUpdateData($productData, $language);
                        $existingProduct->update($updateData);
                        $updated++;
                    } else {
                        // Create new product
                        $newProduct = Product::create($productData);
                        $createdIds[] = $newProduct->id;
                        $imported++;
                    }
                } else {
                    // No product_id, create new
                    $newProduct = Product::create($productData);
                    $createdIds[] = $newProduct->id;
                    $imported++;
                }
            } catch (\Exception $e) {
                $failed++;
                logger()->error('Failed to import product', [
                    'product' => $rawProduct,
                    'error' => $e->getMessage(),
                ]);
            }
        }

        return response()->json([
            'message' => "Successfully imported {$imported} new, updated {$updated} products.".
                ($failed > 0 ? " Failed: {$failed}." : ''),
            'imported' => $imported,
            'updated' => $updated,
            'failed' => $failed,
            'created_ids' => $createdIds,
        ]);
    }

    /**
     * Parse product data from Excel row.
     */
    private function parseProductData(
        array $rawProduct,
        int $categoryId,
        string $source,
        string $language
    ): array {
        $description = $rawProduct['Product Desc'] ?? '';

        return [
            'category_id' => $categoryId,
            'source' => $source,
            'product_id' => $rawProduct['ProductId'] ?? null,
            'image_url' => $rawProduct['Image Url'] ?? null,
            'video_url' => $rawProduct['Video Url'] ?? null,
            'name_ar' => $rawProduct['name_ar'] ?? ($language === 'arabic' ? $description : 'N/A'),
            'name_en' => $rawProduct['name_en'] ?? ($language === 'english' ? $description : 'N/A'),
            'description_ar' => $rawProduct['description_ar'] ?? ($language === 'arabic' ? $description : null),
            'description_en' => $rawProduct['description_en'] ?? ($language === 'english' ? $description : null),
            'price' => $this->parsePrice($rawProduct['Origin Price'] ?? 0),
            'discount_price' => $this->parsePrice($rawProduct['Discount Price'] ?? 0),
            'discount' => $this->parsePrice($rawProduct['Discount'] ?? 0),
            'currency' => $rawProduct['Currency'] ?? 'USD',
            'clicks' => 0,
            'direct_commission_rate' => $this->parsePrice($rawProduct['Direct linking commission rate (%)'] ?? 0),
            'estimated_direct_commission' => $this->parsePrice($rawProduct['Estimated direct linking commission'] ?? 0),
            'indirect_commission_rate' => $this->parsePrice($rawProduct['Indirect linking commission rate (%)'] ?? 0),
            'estimated_indirect_commission' => $this->parsePrice($rawProduct['Estimated indirect linking commission'] ?? 0),
            'sales_180day' => (int) ($rawProduct['Sales180Day'] ?? 0),
            'positive_feedback' => $this->parsePrice($rawProduct['Positive Feedback'] ?? 0),
            'promotion_url' => $rawProduct['Promotion Url'] ?? null,
            'code_name' => $rawProduct['Code Name'] ?? null,
            'code_start_time' => $this->parseDate($rawProduct['Code Start Time'] ?? null),
            'code_end_time' => $this->parseDate($rawProduct['Code End Time'] ?? null),
            'code_value' => $rawProduct['Code Value'] ?? null,
            'code_quantity' => (int) ($rawProduct['Code Quantity'] ?? 0),
            'code_minimum_spend' => $this->parsePrice($rawProduct['Code Minimum Spend'] ?? 0),
        ];
    }

    /**
     * Get only language-specific fields for updating existing products.
     * This prevents overwriting the other language's content.
     */
    private function getLanguageSpecificUpdateData(array $productData, string $language): array
    {
        if ($language === 'arabic') {
            return [
                'name_ar' => $productData['name_ar'],
                'description_ar' => $productData['description_ar'],
                // Update common fields too (images, prices, etc.)
                'image_url' => $productData['image_url'],
                'video_url' => $productData['video_url'],
                'price' => $productData['price'],
                'discount_price' => $productData['discount_price'],
                'discount' => $productData['discount'],
                'currency' => $productData['currency'],
                'direct_commission_rate' => $productData['direct_commission_rate'],
                'estimated_direct_commission' => $productData['estimated_direct_commission'],
                'indirect_commission_rate' => $productData['indirect_commission_rate'],
                'estimated_indirect_commission' => $productData['estimated_indirect_commission'],
                'sales_180day' => $productData['sales_180day'],
                'positive_feedback' => $productData['positive_feedback'],
                'promotion_url' => $productData['promotion_url'],
                'code_name' => $productData['code_name'],
                'code_start_time' => $productData['code_start_time'],
                'code_end_time' => $productData['code_end_time'],
                'code_value' => $productData['code_value'],
                'code_quantity' => $productData['code_quantity'],
                'code_minimum_spend' => $productData['code_minimum_spend'],
            ];
        }

        // English - only update English fields + common fields
        return [
            'name_en' => $productData['name_en'],
            'description_en' => $productData['description_en'],
            // Update common fields too (images, prices, etc.)
            'image_url' => $productData['image_url'],
            'video_url' => $productData['video_url'],
            'price' => $productData['price'],
            'discount_price' => $productData['discount_price'],
            'discount' => $productData['discount'],
            'currency' => $productData['currency'],
            'direct_commission_rate' => $productData['direct_commission_rate'],
            'estimated_direct_commission' => $productData['estimated_direct_commission'],
            'indirect_commission_rate' => $productData['indirect_commission_rate'],
            'estimated_indirect_commission' => $productData['estimated_indirect_commission'],
            'sales_180day' => $productData['sales_180day'],
            'positive_feedback' => $productData['positive_feedback'],
            'promotion_url' => $productData['promotion_url'],
            'code_name' => $productData['code_name'],
            'code_start_time' => $productData['code_start_time'],
            'code_end_time' => $productData['code_end_time'],
            'code_value' => $productData['code_value'],
            'code_quantity' => $productData['code_quantity'],
            'code_minimum_spend' => $productData['code_minimum_spend'],
        ];
    }

    private function parsePrice(mixed $value): ?float
    {
        if (is_numeric($value)) {
            return (float) $value;
        }

        if (is_string($value)) {
            $cleaned = preg_replace('/[^0-9.]/', '', $value);

            return $cleaned !== '' ? (float) $cleaned : null;
        }

        return null;
    }

    private function parseDate(mixed $value): ?string
    {
        if (empty($value)) {
            return null;
        }

        if (is_numeric($value)) {
            return date('Y-m-d H:i:s', \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value)->getTimestamp());
        }

        try {
            return date('Y-m-d H:i:s', strtotime($value));
        } catch (\Exception $e) {
            return null;
        }
    }
}
