<?php

namespace App\Http\Controllers\Api;

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

/**
 * @tags 06. User Subscriptions
 */
class SubscriptionController extends ApiController
{

    /**
     * Get User Categories Subscriptions
     * 
     * Get user's subscribed categories only.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function index(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        // Get only category subscriptions
        $subscriptions = $user->subscriptions()
            ->where('subscribable_type', Category::class)
            ->with(['subscribable'])
            ->orderBy('created_at', 'desc')
            ->get();

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

        $categories = $subscriptions->map(function ($subscription) use ($locale) {
            $category = $subscription->subscribable;
            if (!$category) return null;

            return [
                'subscription_id' => $subscription->id,
                'subscription_type' => $subscription->type,
                'subscribed_at' => $subscription->created_at,
                'category' => [
                    'id' => $category->id,
                    'name' => $category->getName($locale['language_id']),
                    'description' => $category->getDescription($locale['language_id']),
                    'is_featured' => $category->is_featured,
                    'is_active' => $category->is_active,
                    'icon' => $category->getFirstMediaUrl('icon'),
                    'cover' => $category->getFirstMediaUrl('cover'),
                    'offers_count' => $category->offers()->active()->count(),
                ],
            ];
        })->filter()->values();

        return $this->successResponse([
            'categories' => $categories,
            'total_count' => $categories->count(),
        ], 'User category subscriptions retrieved successfully');
    }

    /**
     * Get User Other Subscriptions
     * 
     * Get user's subscribed stores, brands, and offers (everything except categories).
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function others(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        // Get all subscriptions except categories
        $subscriptions = $user->subscriptions()
            ->whereIn('subscribable_type', [
                CountryStore::class,
                Brand::class,
                Offer::class
            ])
            ->with(['subscribable'])
            ->orderBy('created_at', 'desc')
            ->get();

        // Group by type for better organization
        $groupedSubscriptions = $subscriptions->groupBy('subscribable_type');
        $locale = $this->getCurrentLocale($request);

        $result = [
            'stores' => [],
            'brands' => [],
            'offers' => [],
            'total_count' => $subscriptions->count(),
        ];

        foreach ($groupedSubscriptions as $type => $items) {
            switch ($type) {
                case 'App\\Models\\CountryStore':
                    $result['stores'] = $items->map(function ($subscription) use ($locale) {
                        $store = $subscription->subscribable;
                        if (!$store) return null;

                        return [
                            'subscription_id' => $subscription->id,
                            'subscription_type' => $subscription->type,
                            'subscribed_at' => $subscription->created_at,
                            'store' => [
                                'id' => $store->id,
                                'country_id' => $store->country_id,
                                'store_id' => $store->store_id,
                                'name' => $store->store->getName($locale['locale_id']),
                                'description' => $store->store->getDescription($locale['locale_id']),
                                'country_name' => $store->country->getName($locale['language_id']),
                                'is_featured' => $store->is_featured,
                                'is_active' => $store->is_active,
                                'logo' => $store->store->getFirstMediaUrl('logo'),
                                'stats' => [
                                    'followers_count' => $store->stats->followers_count ?? 0,
                                    'offers_count' => $store->offers()->active()->count(),
                                    'avg_discount' => $store->stats->avg_discount ?? 0,
                                    'max_discount' => $store->stats->max_discount ?? 0,
                                ],
                            ],
                        ];
                    })->filter()->values();
                    break;

                case 'App\\Models\\Brand':
                    $result['brands'] = $items->map(function ($subscription) use ($locale) {
                        $brand = $subscription->subscribable;
                        if (!$brand) return null;

                        return [
                            'subscription_id' => $subscription->id,
                            'subscription_type' => $subscription->type,
                            'subscribed_at' => $subscription->created_at,
                            '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,
                                'logo' => $brand->getFirstMediaUrl('logo'),
                                'offers_count' => $brand->offers()->active()->count(),
                            ],
                        ];
                    })->filter()->values();
                    break;

                case 'App\\Models\\Offer':
                    $result['offers'] = $items->map(function ($subscription) use ($locale) {
                        $offer = $subscription->subscribable;
                        if (!$offer) return null;

                        return [
                            'subscription_id' => $subscription->id,
                            'subscription_type' => $subscription->type,
                            'subscribed_at' => $subscription->created_at,
                            'offer' => [
                                'id' => $offer->id,
                                'title' => $offer->getTitle($locale['locale_id']),
                                'description' => $offer->getDescription($locale['locale_id']),
                                'type' => $offer->type,
                                'promotion_type' => $offer->promotion_type,
                                'discount_value' => $offer->discount_value,
                                'is_featured' => $offer->is_featured,
                                'is_active' => $offer->is_active,
                                'is_expired' => $offer->is_expired,
                                'expires_at' => $offer->expires_at,
                                'image' => $offer->getFirstMediaUrl('images'),
                                'store_name' => $offer->countryStore->store->getName($locale['locale_id']),
                                'brand_name' => $offer->brand ? $offer->brand->getName($locale['language_id']) : null,
                            ],
                        ];
                    })->filter()->values();
                    break;
            }
        }

        return $this->successResponse($result, 'User other subscriptions retrieved successfully');
    }

    /**
     * Subscribe to Store
     * 
     * Follow/subscribe to a specific store to get updates about their offers.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    #[BodyParameter('country_store_id', 'ID of the country store to follow', required: true, type: 'integer', example: 1)]
    #[BodyParameter('type', 'Subscription type', required: false, type: 'string', example: 'follow')]
    public function subscribeToStore(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        $validator = Validator::make($request->all(), [
            'country_store_id' => 'required|exists:country_store,id',
            'type' => 'nullable|string|in:follow,notify',
        ]);

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

        $countryStoreId = $request->country_store_id;
        $type = $request->type ?? 'follow';

        // Check if store exists and is active
        $countryStore = CountryStore::with(['store', 'country'])
            ->where('id', $countryStoreId)
            ->active()
            ->first();

        if (!$countryStore) {
            return $this->errorResponse('Store not found or inactive', 404);
        }

        // Check if already subscribed
        $existingSubscription = Subscription::where([
            'user_id' => $user->id,
            'subscribable_type' => CountryStore::class,
            'subscribable_id' => $countryStoreId,
            'type' => $type,
        ])->first();

        if ($existingSubscription) {
            return $this->errorResponse('Already subscribed to this store', 409);
        }

        // Create subscription
        $subscription = Subscription::create([
            'user_id' => $user->id,
            'subscribable_type' => CountryStore::class,
            'subscribable_id' => $countryStoreId,
            'type' => $type,
        ]);

        // Update store followers count
        $countryStore->incrementStat('followers_count');

        $this->logActivity($user, 'subscribed_to_store', [
            'country_store_id' => $countryStoreId,
            'store_name' => $countryStore->store->getName(),
            'type' => $type,
        ]);

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

        return $this->successResponse([
            'subscription' => [
                'id' => $subscription->id,
                'type' => $subscription->type,
                'subscribed_at' => $subscription->created_at,
                'store' => [
                    'id' => $countryStore->id,
                    'name' => $countryStore->store->getName($locale['locale_id']),
                    'country_name' => $countryStore->country->getName($locale['language_id']),
                    'logo' => $countryStore->store->getFirstMediaUrl('logo'),
                ],
            ],
        ], 'Successfully subscribed to store');
    }

    /**
     * Bulk Subscribe to Categories
     * 
     * Subscribe to multiple categories at once.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    #[BodyParameter('category_ids', 'Array of category IDs to subscribe to', required: true, type: 'array', example: [1, 2, 3])]
    #[BodyParameter('type', 'Subscription type for all categories', required: false, type: 'string', example: 'follow')]
    public function bulkSubscribeCategories(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        $validator = Validator::make($request->all(), [
            'category_ids' => 'required|array|min:1|max:20',
            'category_ids.*' => 'required|integer|exists:categories,id',
            'type' => 'nullable|string|in:follow,notify',
        ]);

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

        $categoryIds = $request->category_ids;
        $type = $request->type ?? 'follow';

        // 🔥 أضيف الـ locale هنا
        $locale = $this->getCurrentLocale($request);

        return $this->executeTransaction(function () use ($user, $categoryIds, $type, $locale) {
            $subscribed = [];
            $alreadySubscribed = [];
            $errors = [];

            foreach ($categoryIds as $categoryId) {
                // Load category with translations
                $category = Category::where('id', $categoryId)
                    ->active()
                    ->with(['translations' => function ($q) use ($locale) {
                        $q->where('language_id', $locale['language_id']);
                    }])
                    ->first();

                if (!$category) {
                    $errors[] = "Category ID {$categoryId} not found or inactive";
                    continue;
                }

                // Check if already subscribed
                $existingSubscription = Subscription::where([
                    'user_id' => $user->id,
                    'subscribable_type' => Category::class,
                    'subscribable_id' => $categoryId,
                    'type' => $type,
                ])->first();

                if ($existingSubscription) {
                    $alreadySubscribed[] = [
                        'category_id' => $categoryId,
                        'category_name' => $category->getName($locale['language_id']), // 🔥 FIX
                        'subscription_id' => $existingSubscription->id,
                    ];
                    continue;
                }

                // Create subscription
                $subscription = Subscription::create([
                    'user_id' => $user->id,
                    'subscribable_type' => Category::class,
                    'subscribable_id' => $categoryId,
                    'type' => $type,
                ]);

                $subscribed[] = [
                    'subscription_id' => $subscription->id,
                    'category_id' => $categoryId,
                    'category_name' => $category->getName($locale['language_id']), // 🔥 FIX
                    'subscription_type' => $type,
                    'subscribed_at' => $subscription->created_at,
                ];
            }

            $this->logActivity($user, 'bulk_subscribed_categories', [
                'category_ids' => $categoryIds,
                'subscribed_count' => count($subscribed),
                'already_subscribed_count' => count($alreadySubscribed),
                'errors_count' => count($errors),
                'type' => $type,
            ]);

            return [
                'bulk_subscribe_completed' => true,
                'subscribed' => $subscribed,
                'already_subscribed' => $alreadySubscribed,
                'errors' => $errors,
                'summary' => [
                    'total_requested' => count($categoryIds),
                    'newly_subscribed' => count($subscribed),
                    'already_subscribed' => count($alreadySubscribed),
                    'errors' => count($errors),
                ],
            ];
        }, 'Bulk category subscription completed');
    }
    /**
     * Subscribe to Category
     * 
     * Follow/subscribe to a category to get updates about offers in this category.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    #[BodyParameter('category_id', 'ID of the category to follow', required: true, type: 'integer', example: 1)]
    #[BodyParameter('type', 'Subscription type', required: false, type: 'string', example: 'follow')]
    public function subscribeToCategory(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        $validator = Validator::make($request->all(), [
            'category_id' => 'required|exists:categories,id',
            'type' => 'nullable|string|in:follow,notify',
        ]);

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

        $categoryId = $request->category_id;
        $type = $request->type ?? 'follow';

        // Check if category exists and is active
        $category = Category::where('id', $categoryId)->active()->first();

        if (!$category) {
            return $this->errorResponse('Category not found or inactive', 404);
        }

        // Check if already subscribed
        $existingSubscription = Subscription::where([
            'user_id' => $user->id,
            'subscribable_type' => Category::class,
            'subscribable_id' => $categoryId,
            'type' => $type,
        ])->first();

        if ($existingSubscription) {
            return $this->errorResponse('Already subscribed to this category', 409);
        }

        // Create subscription
        $subscription = Subscription::create([
            'user_id' => $user->id,
            'subscribable_type' => Category::class,
            'subscribable_id' => $categoryId,
            'type' => $type,
        ]);

        $this->logActivity($user, 'subscribed_to_category', [
            'category_id' => $categoryId,
            'category_name' => $category->getName(),
            'type' => $type,
        ]);

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

        return $this->successResponse([
            'subscription' => [
                'id' => $subscription->id,
                'type' => $subscription->type,
                'subscribed_at' => $subscription->created_at,
                'category' => [
                    'id' => $category->id,
                    'name' => $category->getName($locale['language_id']),
                    'icon' => $category->getFirstMediaUrl('icon'),
                ],
            ],
        ], 'Successfully subscribed to category');
    }

    /**
     * Subscribe to Brand
     * 
     * Follow/subscribe to a brand to get updates about their offers.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    #[BodyParameter('brand_id', 'ID of the brand to follow', required: true, type: 'integer', example: 1)]
    #[BodyParameter('type', 'Subscription type', required: false, type: 'string', example: 'follow')]
    public function subscribeToBrand(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        $validator = Validator::make($request->all(), [
            'brand_id' => 'required|exists:brands,id',
            'type' => 'nullable|string|in:follow,notify',
        ]);

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

        $brandId = $request->brand_id;
        $type = $request->type ?? 'follow';

        // Check if brand exists and is active
        $brand = Brand::where('id', $brandId)->active()->first();

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

        // Check if already subscribed
        $existingSubscription = Subscription::where([
            'user_id' => $user->id,
            'subscribable_type' => Brand::class,
            'subscribable_id' => $brandId,
            'type' => $type,
        ])->first();

        if ($existingSubscription) {
            return $this->errorResponse('Already subscribed to this brand', 409);
        }

        // Create subscription
        $subscription = Subscription::create([
            'user_id' => $user->id,
            'subscribable_type' => Brand::class,
            'subscribable_id' => $brandId,
            'type' => $type,
        ]);

        $this->logActivity($user, 'subscribed_to_brand', [
            'brand_id' => $brandId,
            'brand_name' => $brand->getName(),
            'type' => $type,
        ]);

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

        return $this->successResponse([
            'subscription' => [
                'id' => $subscription->id,
                'type' => $subscription->type,
                'subscribed_at' => $subscription->created_at,
                'brand' => [
                    'id' => $brand->id,
                    'name' => $brand->getName($locale['language_id']),
                    'logo' => $brand->getFirstMediaUrl('logo'),
                ],
            ],
        ], 'Successfully subscribed to brand');
    }

    /**
     * Subscribe to Offer
     * 
     * Follow/subscribe to a specific offer to get updates.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    #[BodyParameter('offer_id', 'ID of the offer to follow', required: true, type: 'integer', example: 1)]
    #[BodyParameter('type', 'Subscription type', required: false, type: 'string', example: 'follow')]
    public function subscribeToOffer(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        $validator = Validator::make($request->all(), [
            'offer_id' => 'required|exists:offers,id',
            'type' => 'nullable|string|in:follow,notify,favorite',
        ]);

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

        $offerId = $request->offer_id;
        $type = $request->type ?? 'favorite';

        // Check if offer exists and is active
        $offer = Offer::with(['countryStore.store', 'brand'])
            ->where('id', $offerId)
            ->active()
            ->notExpired()
            ->first();

        if (!$offer) {
            return $this->errorResponse('Offer not found, inactive, or expired', 404);
        }

        // Check if already subscribed
        $existingSubscription = Subscription::where([
            'user_id' => $user->id,
            'subscribable_type' => Offer::class,
            'subscribable_id' => $offerId,
            'type' => $type,
        ])->first();

        if ($existingSubscription) {
            return $this->errorResponse('Already subscribed to this offer', 409);
        }

        // Create subscription
        $subscription = Subscription::create([
            'user_id' => $user->id,
            'subscribable_type' => Offer::class,
            'subscribable_id' => $offerId,
            'type' => $type,
        ]);

        // Update offer favorites count if it's a favorite
        if ($type === 'favorite') {
            $offer->increment('favorites_count');
        }

        $this->logActivity($user, 'subscribed_to_offer', [
            'offer_id' => $offerId,
            'offer_title' => $offer->getTitle(),
            'type' => $type,
        ]);

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

        return $this->successResponse([
            'subscription' => [
                'id' => $subscription->id,
                'type' => $subscription->type,
                'subscribed_at' => $subscription->created_at,
                'offer' => [
                    'id' => $offer->id,
                    'title' => $offer->getTitle($locale['locale_id']),
                    'discount_value' => $offer->discount_value,
                    'image' => $offer->getFirstMediaUrl('images'),
                    'store_name' => $offer->countryStore->store->getName($locale['locale_id']),
                ],
            ],
        ], 'Successfully subscribed to offer');
    }

    /**
     * Unsubscribe from Item
     * 
     * Unfollow/unsubscribe from store, category, brand, or offer.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function unsubscribe(Request $request, $subscriptionId): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        // Find subscription
        $subscription = Subscription::where([
            'id' => $subscriptionId,
            'user_id' => $user->id,
        ])->first();

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

        $subscribableType = $subscription->subscribable_type;
        $subscribableId = $subscription->subscribable_id;
        $type = $subscription->type;

        // Update counts before deletion
        if ($subscribableType === CountryStore::class) {
            $countryStore = CountryStore::find($subscribableId);
            if ($countryStore && $type === 'follow') {
                $countryStore->incrementStat('followers_count', -1);
            }
        } elseif ($subscribableType === Offer::class && $type === 'favorite') {
            $offer = Offer::find($subscribableId);
            if ($offer) {
                $offer->decrement('favorites_count');
            }
        }

        // Delete subscription
        $subscription->delete();

        $this->logActivity($user, 'unsubscribed', [
            'subscription_id' => $subscriptionId,
            'subscribable_type' => $subscribableType,
            'subscribable_id' => $subscribableId,
            'type' => $type,
        ]);

        return $this->successResponse([
            'unsubscribed' => true,
            'subscription_id' => $subscriptionId,
        ], 'Successfully unsubscribed');
    }

    /**
     * Check Subscription Status
     * 
     * Check if user is subscribed to specific item.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function checkStatus(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        $validator = Validator::make($request->all(), [
            'type' => 'required|in:store,category,brand,offer',
            'id' => 'required|integer',
            'subscription_type' => 'nullable|string|in:follow,notify,favorite',
        ]);

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

        $type = $request->type;
        $id = $request->id;
        $subscriptionType = $request->subscription_type ?? 'follow';

        // Map type to model class
        $modelClass = match ($type) {
            'store' => CountryStore::class,
            'category' => Category::class,
            'brand' => Brand::class,
            'offer' => Offer::class,
        };

        // Check subscription
        $subscription = Subscription::where([
            'user_id' => $user->id,
            'subscribable_type' => $modelClass,
            'subscribable_id' => $id,
            'type' => $subscriptionType,
        ])->first();

        return $this->successResponse([
            'is_subscribed' => !is_null($subscription),
            'subscription' => $subscription ? [
                'id' => $subscription->id,
                'type' => $subscription->type,
                'subscribed_at' => $subscription->created_at,
            ] : null,
        ], 'Subscription status retrieved');
    }



    /**
     * Bulk Unsubscribe
     * 
     * Unsubscribe from multiple items at once.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication', required: true, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    #[BodyParameter('subscription_ids', 'Array of subscription IDs to unsubscribe from', required: true, type: 'array', example: [1, 2, 3])]
    public function bulkUnsubscribe(Request $request): JsonResponse
    {
        $user = $request->user();

        if (!$user) {
            return $this->errorResponse('User not authenticated', 401);
        }

        $validator = Validator::make($request->all(), [
            'subscription_ids' => 'required|array|min:1|max:50',
            'subscription_ids.*' => 'integer|exists:subscriptions,id',
        ]);

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

        $subscriptionIds = $request->subscription_ids;

        // Get subscriptions belonging to this user
        $subscriptions = Subscription::whereIn('id', $subscriptionIds)
            ->where('user_id', $user->id)
            ->get();

        if ($subscriptions->count() !== count($subscriptionIds)) {
            return $this->errorResponse('Some subscriptions not found or not owned by user', 404);
        }

        $deletedCount = 0;

        foreach ($subscriptions as $subscription) {
            // Update counts before deletion
            if ($subscription->subscribable_type === CountryStore::class && $subscription->type === 'follow') {
                $countryStore = CountryStore::find($subscription->subscribable_id);
                if ($countryStore) {
                    $countryStore->incrementStat('followers_count', -1);
                }
            } elseif ($subscription->subscribable_type === Offer::class && $subscription->type === 'favorite') {
                $offer = Offer::find($subscription->subscribable_id);
                if ($offer) {
                    $offer->decrement('favorites_count');
                }
            }

            $subscription->delete();
            $deletedCount++;
        }

        $this->logActivity($user, 'bulk_unsubscribed', [
            'subscription_ids' => $subscriptionIds,
            'deleted_count' => $deletedCount,
        ]);

        return $this->successResponse([
            'deleted_count' => $deletedCount,
            'subscription_ids' => $subscriptionIds,
        ], "Successfully unsubscribed from {$deletedCount} items");
    }
}
