<?php

namespace App\Services;

use App\Models\Restaurant;
use App\Repositories\RestaurantRepository;
use App\Repositories\CommissionRuleRepository;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;

class RestaurantService
{
    protected $restaurantRepository;
    protected $commissionRuleRepository;

    public function __construct(RestaurantRepository $restaurantRepository, CommissionRuleRepository $commissionRuleRepository)
    {
        $this->restaurantRepository = $restaurantRepository;
        $this->commissionRuleRepository = $commissionRuleRepository;
    }

    public function createRestaurant(array $data)
    {
        return DB::transaction(function () use ($data) {
            // Handle file uploads
            if (isset($data['logo'])) {
                $data['logo'] = $this->uploadFile($data['logo'], 'restaurants/logos');
            }
            
            if (isset($data['cover_image'])) {
                $data['cover_image'] = $this->uploadFile($data['cover_image'], 'restaurants/covers');
            }

            // Create restaurant
            $restaurant = $this->restaurantRepository->create($data);

            // Attach categories
            if (isset($data['category_ids'])) {
                $restaurant->categories()->attach($data['category_ids']);
            }

            // Create commission rule
            if (isset($data['commission_rate'])) {
                $restaurant->commissionRule()->create([
                    'rate' => $data['commission_rate'],
                    'type' => $data['commission_type'] ?? 'percentage',
                    'is_active' => $data['commission_is_active'] ?? true
                ]);
            }

            return $restaurant;
        });
    }

    public function updateRestaurant(Restaurant $restaurant, array $data)
    {
        return DB::transaction(function () use ($restaurant, $data) {
            // Handle file uploads
            if (isset($data['logo'])) {
                // Delete old logo
                if ($restaurant->logo) {
                    Storage::delete($restaurant->logo);
                }
                $data['logo'] = $this->uploadFile($data['logo'], 'restaurants/logos');
            }
            
            if (isset($data['cover_image'])) {
                // Delete old cover image
                if ($restaurant->cover_image) {
                    Storage::delete($restaurant->cover_image);
                }
                $data['cover_image'] = $this->uploadFile($data['cover_image'], 'restaurants/covers');
            }

            // Update restaurant
            $restaurant = $this->restaurantRepository->update($restaurant, $data);

            // Update categories
            if (isset($data['category_ids'])) {
                $restaurant->categories()->sync($data['category_ids']);
            }

            // Update commission rule
            if (isset($data['commission_rate'])) {
                $restaurant->commissionRule()->updateOrCreate(
                    [],
                    [
                        'rate' => $data['commission_rate'],
                        'type' => $data['commission_type'] ?? 'percentage',
                        'is_active' => $data['commission_is_active'] ?? true
                    ]
                );
            }

            return $restaurant;
        });
    }

    public function approveRestaurant(Restaurant $restaurant)
    {
        return DB::transaction(function () use ($restaurant) {
            $restaurant->update([
                'status' => 'active',
                'approved_at' => now(),
                'approved_by' => auth()->id()
            ]);

            // Notify restaurant owner
            $this->notifyRestaurantOwner($restaurant, 'approved');

            return $restaurant;
        });
    }

    public function rejectRestaurant(Restaurant $restaurant, string $reason)
    {
        return DB::transaction(function () use ($restaurant, $reason) {
            $restaurant->update([
                'status' => 'rejected',
                'rejection_reason' => $reason,
                'rejected_at' => now(),
                'rejected_by' => auth()->id()
            ]);

            // Notify restaurant owner
            $this->notifyRestaurantOwner($restaurant, 'rejected', $reason);

            return $restaurant;
        });
    }

    public function getRestaurantStats(Restaurant $restaurant)
    {
        return [
            'total_orders' => $restaurant->orders()->count(),
            'total_revenue' => $restaurant->orders()->where('status', 'delivered')->sum('total_amount'),
            'average_order_value' => $restaurant->orders()->where('status', 'delivered')->avg('total_amount') ?? 0,
            'total_reviews' => $restaurant->reviews()->count(),
            'average_rating' => $restaurant->reviews()->avg('rating') ?? 0
        ];
    }

    public function searchRestaurants(array $filters = [])
    {
        return $this->restaurantRepository->search($filters);
    }

    private function uploadFile($file, string $path)
    {
        return $file->store($path, 'public');
    }

    private function notifyRestaurantOwner(Restaurant $restaurant, string $action, string $reason = null)
    {
        // Implement notification logic
        // This could be email, SMS, push notification, etc.
        $restaurant->owner->notify(new \App\Notifications\RestaurantStatusUpdated($action, $reason));
    }

    public function suspendRestaurant(Restaurant $restaurant, string $reason)
    {
        if ($restaurant->status === 'suspended') {
            throw new \Exception('Restaurant is already suspended');
        }

        return $this->restaurantRepository->update($restaurant, [
            'status' => 'suspended',
            'operational_status' => 'closed',
            'suspension_reason' => $reason,
            'suspended_at' => now(),
            'suspended_by' => auth()->id()
        ]);
    }

    public function activateRestaurant(Restaurant $restaurant)
    {
        if ($restaurant->status !== 'suspended') {
            throw new \Exception('Restaurant is not suspended');
        }

        return $this->restaurantRepository->update($restaurant, [
            'status' => 'approved',
            'operational_status' => 'open'
        ]);
    }

    public function updateOperationalStatus(Restaurant $restaurant, string $status)
    {
        return $this->restaurantRepository->update($restaurant, [
            'operational_status' => $status
        ]);
    }

    public function getRestaurantAnalytics(Restaurant $restaurant, array $filters = [])
    {
        $startDate = isset($filters['start_date']) ? Carbon::parse($filters['start_date']) : now()->subDays(30);
        $endDate = isset($filters['end_date']) ? Carbon::parse($filters['end_date']) : now();

        $analytics = $this->restaurantRepository->getRestaurantStats($restaurant, $startDate, $endDate);

        // Daily sales for chart
        $dailySales = $restaurant->orders()
            ->whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DATE(created_at) as date, COUNT(*) as orders, SUM(total) as revenue')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        $analytics['daily_sales'] = $dailySales;

        return $analytics;
    }

    public function uploadMedia(Restaurant $restaurant, string $type, $file)
    {
        $path = $this->uploadFile($file, "restaurants/{$type}s");

        switch ($type) {
            case 'logo':
                if ($restaurant->logo) {
                    Storage::disk('public')->delete($restaurant->logo);
                }
                $this->restaurantRepository->update($restaurant, ['logo' => $path]);
                break;
            case 'cover':
                if ($restaurant->cover_image) {
                    Storage::disk('public')->delete($restaurant->cover_image);
                }
                $this->restaurantRepository->update($restaurant, ['cover_image' => $path]);
                break;
            case 'banner':
                $images = $restaurant->images ?? [];
                $images[] = $path;
                $this->restaurantRepository->update($restaurant, ['images' => $images]);
                break;
        }

        return $path;
    }
}
