<?php

namespace App\Services;
use App\Http\Resources\Home\AllCategoriesResource;
use App\Http\Resources\Home\CampaignByOutletResource;
use App\Http\Resources\Home\CurrentOutletResource;
use App\Http\Resources\Home\OtherOutletResource;
use App\Http\Resources\Home\ProductByOutletResource;
use App\Models\Outlet;
use App\Models\Campaign;
use App\Models\Category;
use App\Models\Product;
use App\Models\Tenant;
use App\Traits\Multitenantable;

use Carbon\Carbon;
use function Symfony\Component\Clock\now;

class HomeService
{
    use Multitenantable;

    public function home($outletId)
    {
        $tenantId = config('app.current_tenant_id');

        $tenant = Tenant::withoutGlobalScopes()
        ->select(
        'online_open_time',
        'online_close_time',
        'is_close_service'
        )
        ->where('uuid', $tenantId)
        ->first();

        $currentOutlet = Outlet::select([
        'uuid', 
        'name', 
        'full_address',
        'latitude',
        'longitude',
        'is_active'
        ])
        ->where('uuid', $outletId)
        ->first();

        if(!$currentOutlet) {
            $currentOutlet = Outlet::select([
            'uuid',
            'name',
            'full_address',
            'latitude',
            'longitude',
            'is_active'
            ])
            ->where('is_main_outlet', true)
            ->first();
        }

        $campaigns = Campaign::select([
            'campaigns.uuid',
            'campaigns.action_type',
            'campaigns.action_reference_id',
            'campaigns.server_banner_url'

            ])
            ->with('outlet_campaigns')
            ->whereHas('outlet_campaigns', function($q) use ($currentOutlet) {
                $q->select('outlet_campaigns.uuid')
                ->where('outlet_campaigns.outlet_id', $currentOutlet->uuid);
            })
            ->where('campaigns.is_active', true)
            ->where(function ($q) {
                $q->where(function ($q2) {
                    $q2->where('campaigns.start_date', '<=', Carbon::now()->startOfDay())
                    ->where('campaigns.end_date', '>=', Carbon::now()->startOfDay());
                })->orWhere(function ($q2) {
                    $q2->whereNull('campaigns.start_date')
                    ->whereNull('campaigns.end_date');
                });
            })
            ->get();
        
        $categories = Category::select([
        'uuid',
        'name',
        'server_image_url'

        ])
        ->get();

        $otherOutlets = Outlet::select([
        'uuid',
        'name',
        'phone_number',
        'full_address',
        'latitude',
        'longitude',
        'server_banner_url',
        'is_active'
        ])
        ->whereNot('uuid', $currentOutlet->uuid)
        ->get();

        $productRecommendations = Product::select([
        'products.uuid',
        'products.name',
        'products.server_image_url'
        ])
        ->whereHas('variants', function($q) use ($currentOutlet) {
            $q->select('product_variants.is_visible_online')
            ->whereHas('inventory', function($q2) use ($currentOutlet) {
                $q2->where('outlet_inventories.outlet_id', $currentOutlet->uuid);
            })
            ->where('product_variants.is_visible_online', true);
        })
        ->withSum(['variants as total_sold'], 'total_sold')
        ->withSum(['variants as total_rating'], 'total_rating')
        ->selectRaw('
            (SELECT SUM(average_rating * total_rating) 
            FROM product_variants 
            WHERE product_variants.product_id = products.uuid
            ) / 
            NULLIF((SELECT SUM(total_rating) 
            FROM product_variants 
            WHERE product_variants.product_id = products.uuid
            ), 0) as average_rating
        ')
        ->with([
            'variants.inventory' => function ($q) use ($currentOutlet) {
                $q->select('outlet_inventories.item_id', 'selling_price')
                ->where('outlet_id', $currentOutlet->uuid);
            }
        ])
        ->orderByDesc('total_sold')
        ->orderByDesc('average_rating')
        ->withCount('likes')
        ->take(5)
        ->get();

        $products = Product::select([
        'products.uuid', 
        'products.name', 
        'products.server_image_url'
        ])
        ->whereHas('variants', function($q) use ($currentOutlet) {
            $q->select('product_variants.is_visible_online')
            ->whereHas('inventory', function($q2) use ($currentOutlet) {
                $q2->where('outlet_inventories.outlet_id', $currentOutlet->uuid);
            })
            ->where('product_variants.is_visible_online', true);
        })
        ->withSum(['variants as total_sold'], 'total_sold')
        ->withSum(['variants as total_rating'], 'total_rating')
        ->selectRaw('
            (SELECT SUM(average_rating * total_rating) 
            FROM product_variants 
            WHERE product_variants.product_id = products.uuid
            ) / 
            NULLIF((SELECT SUM(total_rating) 
            FROM product_variants 
            WHERE product_variants.product_id = products.uuid
            ), 0) as average_rating
        ')
        ->with([
            'variants.inventory' => function ($q) use ($currentOutlet) {
                $q->select('outlet_inventories.item_id', 'selling_price')
                ->where('outlet_id', $currentOutlet->uuid);
            }
        ])
        ->orderByDesc('total_sold')
        ->orderByDesc('average_rating')
        ->orderByDesc('created_at')
        ->withCount('likes')
        ->get();

        return [
            'operational_service'     => $tenant,
            'current_outlet'          => new CurrentOutletResource($currentOutlet),
            'campaign_by_outlets'     => CampaignByOutletResource::collection($campaigns),
            'all_categories'          => AllCategoriesResource::collection($categories),
            'other_outlets'           => OtherOutletResource::collection($otherOutlets),
            'product_recommendations' => ProductByOutletResource::collection($productRecommendations),
            'all_products'            => ProductByOutletResource::collection($products)
        ];
    }

    public function getOutlets()
    {
        $outlets = Outlet::select([
        'uuid',
        'name',
        'phone_number',
        'full_address',
        'latitude',
        'longitude',
        'server_banner_url',
        'is_active'
        ])
        ->whereNotNull('full_address')
        ->whereNotNull('latitude')
        ->whereNotNull('longitude')
        ->get(); 
        
        return OtherOutletResource::collection($outlets);
    }

    public function getMainOutlet()
    {
        return Outlet::select([
        'uuid',
        'name',
        'phone_number',
        'full_address',
        'latitude',
        'longitude',
        ])
        ->where('is_main_outlet', true)
        ->first();
    }
}