<?php

namespace App\Http\Controllers\Api;

use App\Models\Occasion;
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 08. Occasions
 */
class OccasionController extends ApiController
{
    /**
     * Get Occasions List
     * 
     * Get all active occasions with localized names and descriptions.
     * Occasions are filtered by user's current country and displayed in user's language.
     */
    #[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 = Occasion::query()
            ->active()
            ->byCountry($locale['country_id'])  // فقط المناسبات المتاحة في البلد الحالي
            ->with(['translations' => function ($q) use ($locale) {
                $q->where('locale_id', $locale['locale_id']);
            }])
            ->withCount([
                '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('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('occasion_translations', function ($join) use ($locale) {
                    $join->on('occasions.id', '=', 'occasion_translations.occasion_id')
                         ->where('occasion_translations.locale_id', $locale['locale_id']);
                })
                ->orderBy('occasion_translations.name', $order);
                break;
            case 'offers_count':
                $query->orderBy('offers_count', $order);
                break;
            case 'popularity':
                // يمكن إضافة نظام Popularity للمناسبات لاحقاً
                $query->orderBy('is_featured', 'desc')
                      ->orderBy('order', 'asc');
                break;
            default: // featured
                $query->orderBy('is_featured', 'desc')
                      ->orderBy('order', 'asc')
                      ->orderBy('id', 'asc');
        }

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

        // Transform data
        $transformedOccasions = $occasions->getCollection()->map(function ($occasion) use ($locale) {
            return [
                'id' => $occasion->id,
                'name' => $occasion->getName($locale['locale_id']),
                'description' => $occasion->getDescription($locale['locale_id']),
                'is_featured' => $occasion->is_featured,
                'is_active' => $occasion->is_active,
                'order' => $occasion->order,
                'offers_count' => $occasion->offers_count,
                'icon' => $occasion->getFirstMediaUrl('icon'),
                'banner' => $occasion->getFirstMediaUrl('banner'),
            ];
        });

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

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

        $occasion = Occasion::query()
            ->where('id', $occasionId)
            ->active()
            ->byCountry($locale['country_id'])
            ->with(['translations' => function ($q) use ($locale) {
                $q->where('locale_id', $locale['locale_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 (!$occasion) {
            return $this->errorResponse('Occasion not found', 404);
        }

        // Get related statistics
        $stats = [
            'total_offers' => $occasion->offers_count,
            'featured_offers' => $occasion->offers()
                ->active()
                ->notExpired()
                ->featured()
                ->whereHas('countryStore', function ($q) use ($locale) {
                    $q->where('country_id', $locale['country_id'])
                      ->active();
                })
                ->count(),
            'total_stores' => $occasion->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' => $occasion->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' => $occasion->offers()
                ->active()
                ->notExpired()
                ->whereHas('countryStore', function ($q) use ($locale) {
                    $q->where('country_id', $locale['country_id'])
                      ->active();
                })
                ->whereNotNull('discount_value')
                ->max('discount_value'),
        ];

        return $this->successResponse([
            'occasion' => [
                'id' => $occasion->id,
                'name' => $occasion->getName($locale['locale_id']),
                'description' => $occasion->getDescription($locale['locale_id']),
                'is_featured' => $occasion->is_featured,
                'is_active' => $occasion->is_active,
                'order' => $occasion->order,
                'icon' => $occasion->getFirstMediaUrl('icon'),
                'banner' => $occasion->getFirstMediaUrl('banner'),
                'stats' => [
                    'offers_count' => $stats['total_offers'],
                    'stores_count' => $stats['total_stores'],
                    'featured_offers_count' => $stats['featured_offers'],
                    'avg_discount' => round($stats['avg_discount'] ?? 0, 2),
                    'max_discount' => round($stats['max_discount'] ?? 0, 2),
                ],
            ],
            'locale' => $locale,
        ], 'Occasion details retrieved successfully');
    }

    /**
     * Get Stores in Occasion
     * 
     * Get all stores that have offers for a specific occasion in the user's country.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication (optional)', required: false, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function stores(Request $request, $occasionId): 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');

        // Check if occasion exists
        $occasion = Occasion::where('id', $occasionId)
                           ->active()
                           ->byCountry($locale['country_id'])
                           ->first();

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

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

        // 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'),
                'occasion_offers_count' => $countryStore->offers_count, // عدد العروض للمناسبة
                'stats' => [
                    'followers_count' => $countryStore->stats->followers_count ?? 0,
                    'popularity' => $countryStore->stats->popularity ?? 0,
                    'avg_discount' => $countryStore->stats->avg_discount ?? 0,
                    'max_discount' => $countryStore->stats->max_discount ?? 0,
                ],
            ];
        });

        return $this->resourceResponse([
            'occasion' => [
                'id' => $occasion->id,
                'name' => $occasion->getName($locale['locale_id']),
                'icon' => $occasion->getFirstMediaUrl('icon'),
            ],
            '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,
                'occasion_id' => $occasionId,
                'country_id' => $locale['country_id'],
                'locale_id' => $locale['locale_id'],
            ],
        ], 'Occasion stores retrieved successfully');
    }

    /**
     * Get Offers in Occasion
     * 
     * Get all active offers that belong to a specific occasion in the user's country.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication (optional)', required: false, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function offers(Request $request, $occasionId): 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',
            'brand_id' => 'nullable|exists:brands,id',
            'category_id' => 'nullable|exists:categories,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);
        $perPage = $request->input('per_page', 20);
        $search = $request->input('search');
        $sort = $request->input('sort', 'newest');
        $order = $request->input('order', 'desc');

        // Check if occasion exists
        $occasion = Occasion::where('id', $occasionId)
                           ->active()
                           ->byCountry($locale['country_id'])
                           ->first();

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

        // Build query for offers in this occasion
        $query = Offer::query()
            ->active()
            ->notExpired()
            ->whereHas('occasions', function ($q) use ($occasionId) {
                $q->where('occasions.id', $occasionId);
            })
            ->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']);
                },
                'brand.translations' => function ($q) use ($locale) {
                    $q->where('language_id', $locale['language_id']);
                },
                'categories.translations' => function ($q) use ($locale) {
                    $q->where('language_id', $locale['language_id']);
                },
                'countryStore.store',
                'brand'
            ]);

        // 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'));
        }

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

        if ($request->filled('category_id')) {
            $query->whereHas('categories', function ($q) use ($request) {
                $q->where('categories.id', $request->input('category_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'),
                ],
                'brand' => $offer->brand ? [
                    'id' => $offer->brand->id,
                    'name' => $offer->brand->getName($locale['language_id']),
                    'logo' => $offer->brand->getFirstMediaUrl('logo'),
                ] : null,
                'categories' => $offer->categories->map(function ($category) use ($locale) {
                    return [
                        'id' => $category->id,
                        'name' => $category->getName($locale['language_id']),
                        'icon' => $category->getFirstMediaUrl('icon'),
                    ];
                }),
                'stats' => [
                    'favorites_count' => $offer->favorites_count,
                    'uses_count' => $offer->uses_count,
                    'views_count' => $offer->views_count,
                    'popularity' => $offer->popularity,
                ],
                'is_favorited' => $isSubscribed,
            ];
        });

        return $this->resourceResponse([
            'occasion' => [
                'id' => $occasion->id,
                'name' => $occasion->getName($locale['locale_id']),
                'icon' => $occasion->getFirstMediaUrl('icon'),
                'banner' => $occasion->getFirstMediaUrl('banner'),
            ],
            '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'),
                'brand_id' => $request->input('brand_id'),
                'category_id' => $request->input('category_id'),
                'search' => $search,
                'sort' => $sort,
                'order' => $order,
                'occasion_id' => $occasionId,
                'country_id' => $locale['country_id'],
                'locale_id' => $locale['locale_id'],
            ],
        ], 'Occasion offers retrieved successfully');
    }

    /**
     * Get Featured Occasions
     * 
     * Get featured occasions for homepage or quick access.
     */
    #[HeaderParameter('Authorization', 'Bearer {token} for authentication (optional)', required: false, type: 'string', example: 'Bearer 1|f832abc...xyz')]
    public function featured(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'limit' => 'nullable|integer|min:1|max:20',
        ]);

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

        $locale = $this->getCurrentLocale($request);
        $limit = $request->input('limit', 10);

        $occasions = Occasion::query()
            ->active()
            ->featured()
            ->byCountry($locale['country_id'])
            ->with(['translations' => function ($q) use ($locale) {
                $q->where('locale_id', $locale['locale_id']);
            }])
            ->withCount([
                'offers' => function ($q) use ($locale) {
                    $q->active()
                      ->notExpired()
                      ->whereHas('countryStore', function ($sq) use ($locale) {
                          $sq->where('country_id', $locale['country_id'])
                            ->active();
                      });
                }
            ])
            ->orderBy('order', 'asc')
            ->orderBy('id', 'asc')
            ->limit($limit)
            ->get();

        $transformedOccasions = $occasions->map(function ($occasion) use ($locale) {
            return [
                'id' => $occasion->id,
                'name' => $occasion->getName($locale['locale_id']),
                'description' => $occasion->getDescription($locale['locale_id']),
                'is_featured' => $occasion->is_featured,
                'order' => $occasion->order,
                'offers_count' => $occasion->offers_count,
                'icon' => $occasion->getFirstMediaUrl('icon'),
                'banner' => $occasion->getFirstMediaUrl('banner'),
            ];
        });

        return $this->successResponse([
            'featured_occasions' => $transformedOccasions,
            'total_count' => $occasions->count(),
            'filters' => [
                'limit' => $limit,
                'country_id' => $locale['country_id'],
                'locale_id' => $locale['locale_id'],
            ],
        ], 'Featured occasions retrieved successfully');
    }
}