<?php

namespace App\Http\Controllers;

use App\Models\Deal;
use App\Models\DealProduct;
use App\Services\ShopifyService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class DealsController extends Controller
{
    public function __construct(
        protected ShopifyService $shopify
    ) {}

    public function index(): View
    {
        $deals = Deal::with('dealProducts')->latest()->paginate(10);
        $activeDeals = Deal::with('dealProducts')
            ->where('restored', false)
            ->whereNotNull('ends_at')
            ->where('ends_at', '>', now())
            ->orderBy('ends_at')
            ->get();
        return view('deals.index', compact('deals', 'activeDeals'));
    }

    /**
     * Search Shopify products by title (API).
     */
    public function search(Request $request): JsonResponse
    {
        $request->validate(['q' => 'nullable|string|max:200']);
        $q = $request->input('q', '');
        $query = $q !== '' ? 'title:*' . preg_replace('/\s+/', '* ', trim($q)) . '*' : 'status:active';

        try {
            $result = $this->shopify->searchProductsByTitle($query, 50);
        } catch (\Throwable $e) {
            return response()->json(['error' => $e->getMessage()], 502);
        }

        $products = [];
        foreach ($result['edges'] ?? [] as $edge) {
            $node = $edge['node'];
            $imageUrl = null;
            $mediaEdges = $node['media']['edges'] ?? [];
            if (!empty($mediaEdges) && !empty($mediaEdges[0]['node']['image']['url'])) {
                $imageUrl = $mediaEdges[0]['node']['image']['url'];
            }
            $variants = $node['variants']['edges'] ?? [];
            foreach ($variants as $ve) {
                $v = $ve['node'];
                $unitCost = $v['inventoryItem']['unitCost']['amount'] ?? null;
                $cost = $unitCost !== null ? (string) round((float) $unitCost, 2) : null;
                $products[] = [
                    'product_id' => $node['id'],
                    'variant_id' => $v['id'],
                    'title' => $node['title'] ?? '',
                    'price' => $v['price'] ?? '0',
                    'compare_at_price' => $v['compareAtPrice'] ?? null,
                    'cost' => $cost,
                    'image_url' => $imageUrl,
                ];
            }
        }

        return response()->json([
            'products' => $products,
            'pageInfo' => $result['pageInfo'] ?? [],
        ]);
    }

    /**
     * Apply deal: sale price = cost + profit (% or fixed), compare at = sale / (1 - discount%/100).
     */
    public function apply(Request $request): JsonResponse
    {
        $request->validate([
            'items' => 'required|array',
            'items.*.variant_id' => 'required|string',
            'items.*.product_id' => 'nullable|string',
            'items.*.title' => 'nullable|string',
            'items.*.price' => 'required|string',
            'items.*.compare_at_price' => 'nullable|string',
            'items.*.cost' => 'nullable|string',
            'profit_type' => 'required|in:percentage,fixed',
            'profit_value' => 'required|numeric|min:0',
            'compare_discount_percent' => 'required|numeric|min:0|max:99.99',
            'duration_value' => 'required|integer|min:1',
            'duration_unit' => 'required|in:hours,days',
        ]);

        $profitType = $request->input('profit_type');
        $profitValue = (float) $request->input('profit_value');
        $compareDiscountPercent = (float) $request->input('compare_discount_percent');
        $durationValue = (int) $request->input('duration_value');
        $durationUnit = $request->input('duration_unit');
        $hours = $durationUnit === 'days' ? $durationValue * 24 : $durationValue;

        $items = $request->input('items');
        $variantIds = array_column($items, 'variant_id');

        // Block: variants already in an active deal
        $activeVariantIds = DealProduct::whereHas('deal', function ($q) {
            $q->where('restored', false)->whereNotNull('ends_at')->where('ends_at', '>', now());
        })->whereIn('shopify_variant_id', $variantIds)->pluck('shopify_variant_id')->all();

        if (!empty($activeVariantIds)) {
            return response()->json([
                'success' => false,
                'message' => 'One or more products are already in an active deal. Remove them from the other deal first, or wait for it to end.',
                'blocked_variants' => $activeVariantIds,
            ], 422);
        }

        $deal = Deal::create([
            'duration_value' => $durationValue,
            'duration_unit' => $durationUnit,
            'starts_at' => now(),
            'ends_at' => now()->addHours($hours),
            'restored' => false,
            'profit_type' => $profitType,
            'profit_value' => $profitValue,
            'compare_discount_percent' => $compareDiscountPercent,
        ]);

        $errors = [];
        $byProduct = [];

        foreach ($items as $item) {
            $variantId = $item['variant_id'];
            $productId = $item['product_id'] ?? null;
            $price = $item['price'];
            $compareAt = $item['compare_at_price'] ?? null;
            $costRaw = $item['cost'] ?? null;
            $cost = $costRaw !== null && $costRaw !== '' ? (float) $costRaw : null;

            if ($cost === null) {
                $errors[] = ($item['title'] ?? 'Product') . ': No cost — skipped';
                continue;
            }

            $originalPrice = (float) $price;
            $originalCompare = $compareAt !== null && $compareAt !== '' ? (float) $compareAt : null;

            if ($profitType === 'percentage') {
                $dealPrice = round($cost + $cost * ($profitValue / 100), 2);
            } else {
                $dealPrice = round($cost + $profitValue, 2);
            }
            $dealPrice = max(0, $dealPrice);
            $denom = 1 - ($compareDiscountPercent / 100);
            $dealCompare = $denom > 0 ? round($dealPrice / $denom, 2) : null;

            DealProduct::create([
                'deal_id' => $deal->id,
                'shopify_product_id' => $productId,
                'shopify_variant_id' => $variantId,
                'title' => $item['title'] ?? null,
                'image_url' => $item['image_url'] ?? null,
                'cost' => $cost,
                'original_price' => $originalPrice,
                'original_compare_at_price' => $originalCompare,
                'deal_price' => $dealPrice,
                'deal_compare_at_price' => $dealCompare,
                'restored' => false,
            ]);

            if ($productId) {
                if (!isset($byProduct[$productId])) {
                    $byProduct[$productId] = [];
                }
                $byProduct[$productId][] = [
                    'id' => $variantId,
                    'price' => (string) $dealPrice,
                    'compareAtPrice' => $dealCompare !== null ? (string) $dealCompare : null,
                ];
            }
        }

        // Update Shopify: bulk by product (same as price-update-testing-collection)
        foreach ($byProduct as $productId => $variants) {
            try {
                $this->shopify->productVariantsBulkUpdate($productId, $variants);
            } catch (\Throwable $e) {
                $errors[] = 'Shopify bulk update (product): ' . $e->getMessage();
            }
        }

        return response()->json([
            'success' => true,
            'deal_id' => $deal->id,
            'message' => count($errors) === 0
                ? 'Deal applied. Prices updated in Shopify. Will restore at ' . $deal->ends_at->toDateTimeString()
                : 'Deal saved. ' . implode(' ', $errors),
        ]);
    }

    public function edit(Deal $deal): View
    {
        $deal->load('dealProducts');
        return view('deals.edit', compact('deal'));
    }

    public function update(Request $request, Deal $deal): RedirectResponse
    {
        $request->validate([
            'ends_at' => 'required|date',
        ]);
        $endsAt = $request->input('ends_at');
        $deal->update(['ends_at' => $endsAt]);
        return redirect()->route('deals.index')->with('success', 'Deal end time updated.');
    }

    public function destroy(Deal $deal): RedirectResponse
    {
        $deal->load('dealProducts');
        if (!$deal->restored) {
            foreach ($deal->dealProducts as $dp) {
                try {
                    $this->shopify->updateVariantPrice(
                        $dp->shopify_variant_id,
                        (string) $dp->original_price,
                        $dp->original_compare_at_price !== null ? (string) $dp->original_compare_at_price : null
                    );
                } catch (\Throwable $e) {
                    // Log and continue so we still delete the deal
                }
            }
        }
        $deal->delete();
        return redirect()->route('deals.index')->with('success', 'Deal deleted. Prices restored in Shopify if they were still active.');
    }
}
