<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\ProductCategory;
use App\Models\ProductImage;
use App\Models\ProductVariant;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ImportController extends Controller
{
    /**
     * Parse a Shopify products CSV and return a preview (no DB writes).
     */
    public function preview(Request $request): JsonResponse
    {
        $request->validate(['file' => 'required|file|mimes:csv,txt|max:10240']);

        $rows = $this->parseCsv($request->file('file')->getRealPath());

        if (empty($rows)) {
            return response()->json(['error' => 'CSV is empty or invalid.'], 422);
        }

        $grouped = $this->groupByHandle($rows);

        $preview = collect($grouped)
            ->filter(fn($g) => trim($g[0]['Title'] ?? '') && !str_contains(strtolower($g[0]['Handle'] ?? ''), '_clone_'))
            ->map(fn($g) => $this->buildPreviewItem($g))
            ->values();

        return response()->json([
            'total'   => $preview->count(),
            'preview' => $preview->take(20),   // show first 20 in UI
        ]);
    }

    /**
     * Actually import the CSV into the database.
     */
    public function import(Request $request): JsonResponse
    {
        $request->validate(['file' => 'required|file|mimes:csv,txt|max:10240']);

        $rows    = $this->parseCsv($request->file('file')->getRealPath());
        $grouped = $this->groupByHandle($rows);

        $created  = 0;
        $updated  = 0;
        $skipped  = 0;
        $errors   = [];

        foreach ($grouped as $handle => $group) {
            try {
                $first  = $group[0];
                $status = strtolower($first['Status'] ?? 'active');
                if ($status === 'true' || $status === '1') $status = 'active';
                if (!in_array($status, ['active', 'draft', 'archived'])) $status = 'active';

                // Skip internal Shopify app products (e.g. BOGOS gift products with no real title)
                $title = trim($first['Title'] ?? '');
                if (!$title || str_contains(strtolower($handle), '_clone_')) {
                    $skipped++;
                    continue;
                }

                $price        = $this->money($first['Variant Price'] ?? $first['Price / United Kingdom'] ?? 0);
                $comparePrice = $this->money($first['Variant Compare At Price'] ?? $first['Compare At Price / United Kingdom'] ?? null);
                $stock        = max(0, (int) ($first['Variant Inventory Qty'] ?? 0));
                $weight       = isset($first['Variant Grams']) && $first['Variant Grams'] !== ''
                    ? (int) $first['Variant Grams'] : null;

                // Use short_description metafield if available, fall back to truncated Body HTML
                $shortDesc = trim($first['short_description (product.metafields.custom.short_description)'] ?? '');
                if (!$shortDesc) {
                    $shortDesc = Str::limit(strip_tags($first['Body (HTML)'] ?? ''), 200);
                }

                $data = [
                    'name'              => $title,
                    'slug'              => Str::slug($handle ?: $title),
                    'description'       => $first['Body (HTML)'] ?? '',
                    'short_description' => $shortDesc,
                    'price'             => $price ?: 0,
                    'compare_price'     => $comparePrice,
                    'stock_quantity'    => $stock,
                    'track_stock'       => true,
                    'status'            => $status,
                    'meta_title'        => $first['SEO Title'] ?? '',
                    'meta_description'  => $first['SEO Description'] ?? '',
                    'weight_grams'      => $weight,
                ];

                // Upsert by slug
                $existing = Product::where('slug', $data['slug'])->first();
                if ($existing) {
                    $existing->update($data);
                    $product = $existing;
                    $updated++;
                } else {
                    $product = Product::create($data);
                    $created++;
                }

                // Categories / Type
                $type = trim($first['Type'] ?? '');
                if ($type) {
                    $cat = ProductCategory::firstOrCreate(
                        ['slug' => Str::slug($type)],
                        ['name' => $type]
                    );
                    $product->categories()->syncWithoutDetaching([$cat->id]);
                }

                // Images — collect all unique image URLs from group rows
                $imagesSynced = [];
                foreach ($group as $i => $row) {
                    $imgSrc = trim($row['Image Src'] ?? '');
                    if ($imgSrc && !in_array($imgSrc, $imagesSynced)) {
                        $imagesSynced[] = $imgSrc;
                        // Only add if not already there
                        if (!$product->images()->where('url', $imgSrc)->exists()) {
                            $isPrimary = $i === 0 && $product->images()->count() === 0;
                            $product->images()->create([
                                'url'        => $imgSrc,
                                'alt_text'   => $row['Image Alt Text'] ?? $product->name,
                                'sort_order' => (int) ($row['Image Position'] ?? ($i + 1)),
                                'is_primary' => $isPrimary,
                            ]);
                        }
                    }
                }

                // Variants — if product has options
                $opt1Name = trim($first['Option1 Name'] ?? '');
                $hasVariants = $opt1Name && strtolower($opt1Name) !== 'title';

                if ($hasVariants) {
                    foreach ($group as $row) {
                        $opt1 = trim($row['Option1 Value'] ?? '');
                        $opt2 = trim($row['Option2 Value'] ?? '');
                        $opt3 = trim($row['Option3 Value'] ?? '');

                        $variantName = array_filter([$opt1, $opt2, $opt3]);
                        $variantName = implode(' / ', $variantName) ?: 'Default';

                        $variantSku  = $row['Variant SKU'] ?? null;
                        $variantPrice = $this->money($row['Variant Price'] ?? $row['Price / United Kingdom'] ?? $price);
                        $variantStock = max(0, (int) ($row['Variant Inventory Qty'] ?? 0));

                        $attributes = array_filter([
                            $first['Option1 Name'] ?? null => $opt1 ?: null,
                            ($first['Option2 Name'] ?? null) => $opt2 ?: null,
                            ($first['Option3 Name'] ?? null) => $opt3 ?: null,
                        ]);

                        // Check if variant already exists (by name)
                        $existingVariant = $product->variants()->where('name', $variantName)->first();
                        if (!$existingVariant) {
                            $product->variants()->create([
                                'name'           => $variantName,
                                'sku'            => $variantSku ?: null,
                                'price'          => $variantPrice ?: $price,
                                'stock_quantity' => $variantStock,
                                'attributes'     => $attributes ?: null,
                            ]);
                        }
                    }
                }

            } catch (\Throwable $e) {
                $errors[] = "Row '{$handle}': " . $e->getMessage();
                $skipped++;
            }
        }

        return response()->json([
            'message' => "Import complete.",
            'created' => $created,
            'updated' => $updated,
            'skipped' => $skipped,
            'errors'  => $errors,
        ]);
    }

    // ── Helpers ──────────────────────────────────────────────────────────────

    private function parseCsv(string $path): array
    {
        $rows    = [];
        $headers = null;

        if (($fh = fopen($path, 'r')) === false) return [];

        while (($row = fgetcsv($fh, 0, ',')) !== false) {
            if ($headers === null) {
                // Strip BOM if present
                $row[0] = ltrim($row[0], "\xEF\xBB\xBF");
                $headers = $row;
                continue;
            }
            if (count($row) !== count($headers)) continue;
            $rows[] = array_combine($headers, $row);
        }

        fclose($fh);
        return $rows;
    }

    private function groupByHandle(array $rows): array
    {
        $grouped = [];
        foreach ($rows as $row) {
            $handle = $row['Handle'] ?? '';
            // Rows without a handle extend the previous product (images/variants)
            if (!$handle && !empty($grouped)) {
                $lastKey = array_key_last($grouped);
                $grouped[$lastKey][] = $row;
            } else {
                $grouped[$handle][] = $row;
            }
        }
        return $grouped;
    }

    private function buildPreviewItem(array $group): array
    {
        $first = $group[0];
        $images = array_values(array_unique(array_filter(array_column($group, 'Image Src'))));
        $variantRows = array_filter($group, fn($r) => trim($r['Option1 Name'] ?? '') && strtolower(trim($r['Option1 Name'] ?? '')) !== 'title');

        return [
            'handle'         => $first['Handle'] ?? '',
            'title'          => $first['Title'] ?? '',
            'type'           => $first['Type'] ?? '',
            'price'          => $this->money($first['Variant Price'] ?? $first['Price / United Kingdom'] ?? 0),
            'compare_price'  => $this->money($first['Variant Compare At Price'] ?? $first['Compare At Price / United Kingdom'] ?? null),
            'stock'          => max(0, (int) ($first['Variant Inventory Qty'] ?? 0)),
            'status'         => $first['Status'] ?? 'active',
            'image'          => $images[0] ?? null,
            'image_count'    => count($images),
            'variant_count'  => count($group),
            'has_variants'   => count($variantRows) > 0,
        ];
    }

    private function money($val): ?float
    {
        if ($val === null || $val === '') return null;
        $clean = preg_replace('/[^0-9.]/', '', (string) $val);
        return $clean !== '' ? (float) $clean : null;
    }
}
