<?php

namespace App\Http\Controllers\Api;

use App\Models\Brand;
use App\Models\CountryStore;
use App\Models\Offer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Dedoc\Scramble\Attributes\HeaderParameter;

/**
 * @tags 06. Brands
 */
class BrandController extends ApiController
{
    /**
     * Get Brands List
     * 
     * Get all active brands with localizedا names and descriptions.
     * Shows brands that have active offers in user's current country.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication (optional)', required: false, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function index(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'featured' => 'nullable|boolean',
            'page' => 'nullable|integer|min:1',
            'per_page' => 'nullable|integer|min:1|max:50',
            'search' => 'nullable|string|max:100',
            'sort' => 'nullable|in:name,featured,offers_count,popularity',
            'order' => 'nullable|in:asc,desc',
        ]);

        if ($validator->fails()) {
            return $this->validationErrorResponse($validator->errors());
        }

        $locale = $this->getCurrentLocale($request);
        $perPage = $request->input('per_page', 20);
        $search = $request->input('search');
        $featured = $request->input('featured');
        $sort = $request->input('sort', 'featured');
        $order = $request->input('order', 'desc');

        // Build query
        $query = Brand::query()
            ->active()
            ->with(['translations' => function ($q) use ($locale) {
                $q->where('language_id', $locale['language_id']);
            }])
            ->withCount([
                'offers' => function ($q) use ($locale) {
                    $q->active()
                        ->notExpired()
                        ->whereHas('countryStore', function ($sq) use ($locale) {
                            $sq->where('country_id', $locale['country_id'])
                                ->active();
                        });
                }
            ])
            // Only show brands that have offers in user's country
            ->whereHas('offers', function ($q) use ($locale) {
                $q->active()
                    ->notExpired()
                    ->whereHas('countryStore', function ($sq) use ($locale) {
                        $sq->where('country_id', $locale['country_id'])
                            ->active();
                    });
            });

        // Apply featured filter
        if ($featured !== null) {
            $query->where('is_featured', $featured);
        }

        // Apply search filter
        if ($search) {
            $query->whereHas('translations', function ($q) use ($search, $locale) {
                $q->where('language_id', $locale['language_id'])
                    ->where(function ($sq) use ($search) {
                        $sq->where('name', 'like', "%{$search}%")
                            ->orWhere('description', 'like', "%{$search}%");
                    });
            });
        }

        // Apply sorting
        switch ($sort) {
            case 'name':
                $query->join('brand_translations', function ($join) use ($locale) {
                    $join->on('brands.id', '=', 'brand_translations.brand_id')
                        ->where('brand_translations.language_id', $locale['language_id']);
                })
                    ->orderBy('brand_translations.name', $order);
                break;
            case 'offers_count':
                $query->orderBy('offers_count', $order);
                break;
            case 'popularity':
                // Calculate popularity based on offers stats
                $query->leftJoin('offers', 'brands.id', '=', 'offers.brand_id')
                    ->selectRaw('brands.*, COALESCE(SUM(offers.popularity), 0) as total_popularity')
                    ->groupBy('brands.id')
                    ->orderBy('total_popularity', $order);
                break;
            default: // featured
                $query->orderBy('is_featured', 'desc')
                    ->orderBy('order', 'asc')
                    ->orderBy('id', 'asc');
        }

        $brands = $query->select('brands.*')->paginate($perPage);

        // Transform data
        $transformedBrands = $brands->getCollection()->map(function ($brand) use ($locale, $request) {
            $isSubscribed = false;
            if ($request->user()) {
                $isSubscribed = $request->user()->isSubscribedTo($brand, 'follow');
            }

            return [
                'id' => $brand->id,
                'name' => $brand->getName($locale['language_id']),
                'description' => $brand->getDescription($locale['language_id']),
                'is_featured' => $brand->is_featured,
                'is_active' => $brand->is_active,
                'order' => $brand->order,
                'offers_count' => $brand->offers_count,
                'logo' => $brand->getFirstMediaUrl('logo'),
                'is_subscribed' => $isSubscribed,
            ];
        });

        return $this->resourceResponse([
            'brands' => $transformedBrands,
            'pagination' => [
                'current_page' => $brands->currentPage(),
                'last_page' => $brands->lastPage(),
                'per_page' => $brands->perPage(),
                'total' => $brands->total(),
                'from' => $brands->firstItem(),
                'to' => $brands->lastItem(),
            ],
            'filters' => [
                'featured' => $featured,
                'search' => $search,
                'sort' => $sort,
                'order' => $order,
                'country_id' => $locale['country_id'],
                'language_id' => $locale['language_id'],
            ],
        ], 'Brands retrieved successfully');
    }

    /**
     * Get Brand Details
     * 
     * Get detailed information about a specific brand including statistics.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication (optional)', required: false, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function show(Request $request, $brandId): JsonResponse
    {
        $locale = $this->getCurrentLocale($request);

        $brand = Brand::query()
            ->where('id', $brandId)
            ->active()
            ->with(['translations' => function ($q) use ($locale) {
                $q->where('language_id', $locale['language_id']);
            }])
            ->withCount([
                'offers' => function ($q) use ($locale) {
                    $q->active()
                        ->notExpired()
                        ->whereHas('countryStore', function ($sq) use ($locale) {
                            $sq->where('country_id', $locale['country_id'])
                                ->active();
                        });
                }
            ])
            ->first();

        if (!$brand) {
            return $this->errorResponse('Brand not found', 404);
        }

        // Get brand statistics
        $stats = [
            'total_offers' => $brand->offers_count,
            'active_stores' => $brand->offers()
                ->active()
                ->notExpired()
                ->whereHas('countryStore', function ($q) use ($locale) {
                    $q->where('country_id', $locale['country_id'])
                        ->active();
                })
                ->distinct('country_store_id')
                ->count('country_store_id'),
            'avg_discount' => $brand->offers()
                ->active()
                ->notExpired()
                ->whereHas('countryStore', function ($q) use ($locale) {
                    $q->where('country_id', $locale['country_id'])
                        ->active();
                })
                ->whereNotNull('discount_value')
                ->avg('discount_value'),
            'max_discount' => $brand->offers()
                ->active()
                ->notExpired()
                ->whereHas('countryStore', function ($q) use ($locale) {
                    $q->where('country_id', $locale['country_id'])
                        ->active();
                })
                ->whereNotNull('discount_value')
                ->max('discount_value'),
        ];

        // Check if user is subscribed and get subscription details
        $isSubscribed = false;
        $subscriptionId = null;
        if ($request->user()) {
            $subscription = $request->user()->subscriptions()
                ->where('subscribable_type', Brand::class)
                ->where('subscribable_id', $brandId)
                ->first();

            if ($subscription) {
                $isSubscribed = true;
                $subscriptionId = $subscription->id;
            }
        }

        return $this->successResponse([
            'brand' => [
                'id' => $brand->id,
                'name' => $brand->getName($locale['language_id']),
                'description' => $brand->getDescription($locale['language_id']),
                'is_featured' => $brand->is_featured,
                'is_active' => $brand->is_active,
                'order' => $brand->order,
                'logo' => $brand->getFirstMediaUrl('logo'),
                'stats' => [
                    'offers_count' => $stats['total_offers'],
                    'stores_count' => $stats['active_stores'],
                    'avg_discount' => round($stats['avg_discount'] ?? 0, 2),
                    'max_discount' => round($stats['max_discount'] ?? 0, 2),
                ],
                'is_subscribed' => $isSubscribed,
                'subscription_id' => $subscriptionId, // 🔥 NEW
            ],
            'locale' => $locale,
        ], 'Brand details retrieved successfully');
    }


    /**
     * Get Brand Stores
     * 
     * Get all stores that sell products from this brand in user's country.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication (optional)', required: false, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function stores(Request $request, $brandId): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'featured' => 'nullable|boolean',
            'page' => 'nullable|integer|min:1',
            'per_page' => 'nullable|integer|min:1|max:50',
            'search' => 'nullable|string|max:100',
            'sort' => 'nullable|in:name,featured,offers_count,popularity',
            'order' => 'nullable|in:asc,desc',
        ]);

        if ($validator->fails()) {
            return $this->validationErrorResponse($validator->errors());
        }

        $locale = $this->getCurrentLocale($request);

        // Check if brand exists
        $brand = Brand::where('id', $brandId)->active()->first();
        if (!$brand) {
            return $this->errorResponse('Brand not found', 404);
        }

        $perPage = $request->input('per_page', 20);
        $search = $request->input('search');
        $featured = $request->input('featured');
        $sort = $request->input('sort', 'featured');
        $order = $request->input('order', 'desc');

        // Build query for stores that have offers from this brand
        $query = CountryStore::query()
            ->where('country_id', $locale['country_id'])
            ->active()
            ->whereHas('offers', function ($q) use ($brandId) {
                $q->where('brand_id', $brandId)
                    ->active()
                    ->notExpired();
            })
            ->with([
                'store.translations' => function ($q) use ($locale) {
                    $q->where('locale_id', $locale['locale_id']);
                },
                'store',
                'stats'
            ])
            ->withCount([
                'offers' => function ($q) use ($brandId) {
                    $q->where('brand_id', $brandId)
                        ->active()
                        ->notExpired();
                }
            ]);

        // Apply featured filter
        if ($featured !== null) {
            $query->where('is_featured', $featured);
        }

        // Apply search filter
        if ($search) {
            $query->whereHas('store.translations', function ($q) use ($search, $locale) {
                $q->where('locale_id', $locale['locale_id'])
                    ->where(function ($sq) use ($search) {
                        $sq->where('name', 'like', "%{$search}%")
                            ->orWhere('description', 'like', "%{$search}%");
                    });
            });
        }

        // Apply sorting
        switch ($sort) {
            case 'name':
                $query->join('stores', 'country_store.store_id', '=', 'stores.id')
                    ->join('store_translations', function ($join) use ($locale) {
                        $join->on('stores.id', '=', 'store_translations.store_id')
                            ->where('store_translations.locale_id', $locale['locale_id']);
                    })
                    ->orderBy('store_translations.name', $order);
                break;
            case 'offers_count':
                $query->orderBy('offers_count', $order);
                break;
            case 'popularity':
                $query->leftJoin('country_store_stats', 'country_store.id', '=', 'country_store_stats.country_store_id')
                    ->orderBy('country_store_stats.popularity', $order);
                break;
            default: // featured
                $query->orderBy('is_featured', 'desc')
                    ->orderBy('order', 'asc');
        }

        $stores = $query->select('country_store.*')->paginate($perPage);

        // Transform data
        $transformedStores = $stores->getCollection()->map(function ($countryStore) use ($locale) {
            return [
                'id' => $countryStore->id,
                'store_id' => $countryStore->store_id,
                'name' => $countryStore->store->getName($locale['locale_id']),
                'description' => $countryStore->store->getDescription($locale['locale_id']),
                'is_featured' => $countryStore->is_featured,
                'is_active' => $countryStore->is_active,
                'logo' => $countryStore->store->getFirstMediaUrl('logo'),
                'brand_offers_count' => $countryStore->offers_count, // Offers from this specific brand
                'stats' => [
                    'followers_count' => $countryStore->stats->followers_count ?? 0,
                    'popularity' => $countryStore->stats->popularity ?? 0,
                ],
            ];
        });

        return $this->resourceResponse([
            'brand' => [
                'id' => $brand->id,
                'name' => $brand->getName($locale['language_id']),
                'logo' => $brand->getFirstMediaUrl('logo'),
            ],
            'stores' => $transformedStores,
            'pagination' => [
                'current_page' => $stores->currentPage(),
                'last_page' => $stores->lastPage(),
                'per_page' => $stores->perPage(),
                'total' => $stores->total(),
                'from' => $stores->firstItem(),
                'to' => $stores->lastItem(),
            ],
            'filters' => [
                'featured' => $featured,
                'search' => $search,
                'sort' => $sort,
                'order' => $order,
                'brand_id' => $brandId,
                'country_id' => $locale['country_id'],
                'locale_id' => $locale['locale_id'],
            ],
        ], 'Brand stores retrieved successfully');
    }

    /**
     * Get Brand Offers
     * 
     * Get all active offers from this brand in user's country.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication (optional)', required: false, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function offers(Request $request, $brandId): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'featured' => 'nullable|boolean',
            'exclusive' => 'nullable|boolean',
            'free_shipping' => 'nullable|boolean',
            'new_customer' => 'nullable|boolean',
            'min_discount' => 'nullable|numeric|min:0|max:100',
            'type' => 'nullable|in:coupon,deal,cashback',
            'promotion_type' => 'nullable|in:percentage,fixed,bogo,gift',
            'store_id' => 'nullable|exists:country_store,id',
            'page' => 'nullable|integer|min:1',
            'per_page' => 'nullable|integer|min:1|max:50',
            'search' => 'nullable|string|max:100',
            'sort' => 'nullable|in:newest,discount,popularity,expiry',
            'order' => 'nullable|in:asc,desc',
        ]);

        if ($validator->fails()) {
            return $this->validationErrorResponse($validator->errors());
        }

        $locale = $this->getCurrentLocale($request);

        // Check if brand exists
        $brand = Brand::where('id', $brandId)->active()->first();
        if (!$brand) {
            return $this->errorResponse('Brand not found', 404);
        }

        $perPage = $request->input('per_page', 20);
        $search = $request->input('search');
        $sort = $request->input('sort', 'newest');
        $order = $request->input('order', 'desc');

        // Build query for brand offers
        $query = Offer::query()
            ->where('brand_id', $brandId)
            ->active()
            ->notExpired()
            ->whereHas('countryStore', function ($q) use ($locale) {
                $q->where('country_id', $locale['country_id'])
                    ->active();
            })
            ->with([
                'translations' => function ($q) use ($locale) {
                    $q->where('locale_id', $locale['locale_id']);
                },
                'countryStore.store.translations' => function ($q) use ($locale) {
                    $q->where('locale_id', $locale['locale_id']);
                },
                'countryStore.store',
                'categories.translations' => function ($q) use ($locale) {
                    $q->where('language_id', $locale['language_id']);
                }
            ]);

        // Apply filters
        if ($request->filled('featured')) {
            $query->where('is_featured', $request->boolean('featured'));
        }

        if ($request->filled('exclusive')) {
            $query->where('is_exclusive', $request->boolean('exclusive'));
        }

        if ($request->filled('free_shipping')) {
            $query->where('is_free_shipping', $request->boolean('free_shipping'));
        }

        if ($request->filled('new_customer')) {
            $query->where('is_new_customer', $request->boolean('new_customer'));
        }

        if ($request->filled('min_discount')) {
            $query->where('discount_value', '>=', $request->input('min_discount'));
        }

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

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

        if ($request->filled('store_id')) {
            $query->where('country_store_id', $request->input('store_id'));
        }

        // Apply search filter
        if ($search) {
            $query->whereHas('translations', function ($q) use ($search, $locale) {
                $q->where('locale_id', $locale['locale_id'])
                    ->where(function ($sq) use ($search) {
                        $sq->where('title', 'like', "%{$search}%")
                            ->orWhere('description', 'like', "%{$search}%");
                    });
            });
        }

        // Apply sorting
        switch ($sort) {
            case 'discount':
                $query->orderBy('discount_value', $order);
                break;
            case 'popularity':
                $query->orderBy('popularity', $order);
                break;
            case 'expiry':
                $query->orderByRaw('expires_at IS NULL, expires_at ' . $order);
                break;
            default: // newest
                $query->orderBy('created_at', $order);
        }

        $offers = $query->paginate($perPage);

        // Transform data
        $transformedOffers = $offers->getCollection()->map(function ($offer) use ($locale, $request) {
            $isSubscribed = false;
            if ($request->user()) {
                $isSubscribed = $request->user()->isSubscribedTo($offer, 'favorite');
            }

            return [
                'id' => $offer->id,
                'title' => $offer->getTitle($locale['locale_id']),
                'description' => $offer->getDescription($locale['locale_id']),
                'type' => $offer->type,
                'code' => $offer->code,
                'promotion_type' => $offer->promotion_type,
                'discount_value' => $offer->discount_value,
                'regular_price' => $offer->regular_price,
                'sale_price' => $offer->sale_price,
                'currency' => $offer->currency,
                'is_featured' => $offer->is_featured,
                'is_exclusive' => $offer->is_exclusive,
                'is_free_shipping' => $offer->is_free_shipping,
                'is_new_customer' => $offer->is_new_customer,
                'expires_at' => $offer->expires_at?->toISOString(),
                'is_expired' => $offer->is_expired,
                'image' => $offer->getFirstMediaUrl('images'),
                'store' => [
                    'id' => $offer->countryStore->id,
                    'name' => $offer->countryStore->store->getName($locale['locale_id']),
                    'logo' => $offer->countryStore->store->getFirstMediaUrl('logo'),
                ],
                'categories' => $offer->categories->map(function ($category) use ($locale) {
                    return [
                        'id' => $category->id,
                        'name' => $category->getName($locale['language_id']),
                    ];
                }),
                'stats' => [
                    'favorites_count' => $offer->favorites_count,
                    'uses_count' => $offer->uses_count,
                    'views_count' => $offer->views_count,
                ],
                'is_favorited' => $isSubscribed,
            ];
        });

        return $this->resourceResponse([
            'brand' => [
                'id' => $brand->id,
                'name' => $brand->getName($locale['language_id']),
                'logo' => $brand->getFirstMediaUrl('logo'),
            ],
            'offers' => $transformedOffers,
            'pagination' => [
                'current_page' => $offers->currentPage(),
                'last_page' => $offers->lastPage(),
                'per_page' => $offers->perPage(),
                'total' => $offers->total(),
                'from' => $offers->firstItem(),
                'to' => $offers->lastItem(),
            ],
            'filters' => [
                'featured' => $request->input('featured'),
                'exclusive' => $request->input('exclusive'),
                'free_shipping' => $request->input('free_shipping'),
                'new_customer' => $request->input('new_customer'),
                'min_discount' => $request->input('min_discount'),
                'type' => $request->input('type'),
                'promotion_type' => $request->input('promotion_type'),
                'store_id' => $request->input('store_id'),
                'search' => $search,
                'sort' => $sort,
                'order' => $order,
                'brand_id' => $brandId,
                'country_id' => $locale['country_id'],
                'locale_id' => $locale['locale_id'],
            ],
        ], 'Brand offers retrieved successfully');
    }
}
