<?php
// app/Http/Controllers/Api/Admin/PromoController.php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Traits\ApiResponse;
use App\Models\Promo;
use App\Http\Requests\Api\Admin\PromoRequest;
use App\Http\Resources\Api\PromoResource;
use App\Http\Resources\Api\PromoCollection;
use Illuminate\Http\Request;
use Carbon\Carbon;

class PromoController extends Controller
{
    use ApiResponse;

    /**
     * Get all promos with pagination and search
     */
    public function index(Request $request)
    {
        try {
            $query = Promo::when($request->search, function ($q, $search) {
                    $q->where('name', 'like', "%{$search}%")
                      ->orWhere('description', 'like', "%{$search}%")
                      ->orWhere('code', 'like', "%{$search}%");
                })
                ->when($request->type, function ($q, $type) {
                    $q->where('type', $type);
                })
                ->when($request->status, function ($q, $status) {
                    if ($status === 'active') {
                        $q->where('is_active', true)
                          ->where('start_date', '<=', now())
                          ->where('end_date', '>=', now());
                    } elseif ($status === 'inactive') {
                        $q->where('is_active', false);
                    } elseif ($status === 'expired') {
                        $q->where('end_date', '<', now());
                    } elseif ($status === 'upcoming') {
                        $q->where('start_date', '>', now());
                    }
                })
                ->orderBy('created_at', 'desc');

            $perPage = $request->per_page ?? 20;
            $promos = $query->paginate($perPage);

            return $this->successResponse(
                new PromoCollection($promos),
                'Promos retrieved successfully'
            );
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to retrieve promos', 500, $e->getMessage());
        }
    }

    /**
     * Get single promo
     */
    public function show($id)
    {
        try {
            $promo = Promo::find($id);

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

            return $this->successResponse(
                new PromoResource($promo),
                'Promo retrieved successfully'
            );
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to retrieve promo', 500, $e->getMessage());
        }
    }

    /**
     * Create new promo
     */
    public function store(PromoRequest $request)
    {
        try {
            // Check for duplicate code
            if ($request->code) {
                $existingPromo = Promo::where('code', $request->code)->first();
                if ($existingPromo) {
                    return $this->errorResponse('Promo code already exists', 400);
                }
            }

            // Validate dates
            $startDate = Carbon::parse($request->start_date);
            $endDate = Carbon::parse($request->end_date);

            if ($endDate->lessThan($startDate)) {
                return $this->errorResponse('End date must be after start date', 400);
            }

            $promo = Promo::create($request->validated());

            return $this->successResponse(
                new PromoResource($promo),
                'Promo created successfully',
                201
            );
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to create promo', 500, $e->getMessage());
        }
    }

    /**
     * Update promo
     */
    public function update(PromoRequest $request, $id)
    {
        try {
            $promo = Promo::find($id);

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

            // Check for duplicate code
            if ($request->code && $request->code !== $promo->code) {
                $existingPromo = Promo::where('code', $request->code)->first();
                if ($existingPromo) {
                    return $this->errorResponse('Promo code already exists', 400);
                }
            }

            // Validate dates
            if ($request->has('start_date') || $request->has('end_date')) {
                $startDate = Carbon::parse($request->start_date ?? $promo->start_date);
                $endDate = Carbon::parse($request->end_date ?? $promo->end_date);

                if ($endDate->lessThan($startDate)) {
                    return $this->errorResponse('End date must be after start date', 400);
                }
            }

            $promo->update($request->validated());

            return $this->successResponse(
                new PromoResource($promo->fresh()),
                'Promo updated successfully'
            );
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to update promo', 500, $e->getMessage());
        }
    }

    /**
     * Delete promo
     */
    public function destroy($id)
    {
        try {
            $promo = Promo::find($id);

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

            $promo->delete();

            return $this->successResponse(
                null,
                'Promo deleted successfully'
            );
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to delete promo', 500, $e->getMessage());
        }
    }

    /**
     * Toggle promo status
     */
    public function toggleStatus($id)
    {
        try {
            $promo = Promo::find($id);

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

            $promo->update(['is_active' => !$promo->is_active]);

            return $this->successResponse(
                new PromoResource($promo),
                'Promo status updated successfully'
            );
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to update promo status', 500, $e->getMessage());
        }
    }

    /**
     * Get promo statistics
     */
    public function statistics()
    {
        try {
            $totalPromos = Promo::count();
            $activePromos = Promo::where('is_active', true)
                ->where('start_date', '<=', now())
                ->where('end_date', '>=', now())
                ->count();
            $expiredPromos = Promo::where('end_date', '<', now())->count();
            $upcomingPromos = Promo::where('start_date', '>', now())->count();

            $byType = Promo::selectRaw('type, count(*) as count')
                ->groupBy('type')
                ->get();

            return $this->successResponse([
                'total_promos' => $totalPromos,
                'active_promos' => $activePromos,
                'expired_promos' => $expiredPromos,
                'upcoming_promos' => $upcomingPromos,
                'by_type' => $byType,
                'expiring_soon' => Promo::where('end_date', '>=', now())
                    ->where('end_date', '<=', now()->addDays(7))
                    ->where('is_active', true)
                    ->orderBy('end_date')
                    ->limit(5)
                    ->get()
                    ->map(function ($promo) {
                        return [
                            'id' => $promo->id,
                            'name' => $promo->name,
                            'code' => $promo->code,
                            'end_date' => $promo->end_date,
                            'days_left' => Carbon::parse($promo->end_date)->diffInDays(now())
                        ];
                    })
            ], 'Promo statistics retrieved successfully');
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to retrieve statistics', 500, $e->getMessage());
        }
    }
}