<?php

namespace App\Http\Controllers\Reports;

use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use App\Models\CompanyConnection;
use App\Models\CompanyModule;
use App\Models\Container;
use App\Models\Order;
use App\Models\Package;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class MonthlyReportController
{
    public function salesReport(Request $request): JsonResponse {
        $from = $request->route('from') ? Carbon::parse($request->route('from')) : Carbon::now()->startOfMonth();
        $to = $request->route('to') ? Carbon::parse($request->route('to')) : Carbon::now()->endOfMonth();

        $receivedCbm = Package::warehouseReceiveList()->whereHas('deliveryTransports', function ($transport) use ($from, $to) {
            return $transport->whereBetween('drop_date', [$from, $to]);
        })->get()->sum(function($package){
            return (( (float) $package->width / 100) * ( (float) $package->length / 100) * ( (float) $package->height / 100)) * $package->quantity;
        });

        $containers = Container::whereBetween('loading_date', [$from, $to])->orderBy('loading_date')->get();

        $customers = $containers->flatMap(function ($container) {
            return $container->companyModules;
        })->unique();

        $orders = $containers->flatMap(function ($container) {
            return $container->orders;
        })->unique();

        $packages = $containers->flatMap(function ($container) {
            return $container->packages;
        });

        $totalCbm = $packages->sum(function($package){
            return (( (float) $package->width / 100) * ( (float) $package->length / 100) * ( (float) $package->height / 100)) * $package->quantity;
        });

        $newCustomers = CompanyModule::where('type', BusinessType::IMPORTER)->whereBetween('created_at', [$from, $to])->count();
        $newConvertedCustomers = CompanyModule::where('type', BusinessType::IMPORTER)->whereBetween('created_at', [$from, $to])->whereHas('orders', function($order){
            return $order->whereHas('packingLists');
        })->count();

        $startDay = $request->route('to') ? Carbon::parse($request->route('to')) : Carbon::now();
        $days = $startDay->addDay()->diffInDaysFiltered(function (Carbon $date) {

            return $date->isWeekday();

        }, $request->route('to') ? Carbon::parse($request->route('to'))->endOfMonth() : Carbon::now()->endOfMonth());

        return (new ApiResponseObject('fetch monthly report Successful',
            '',
            HttpStatus::OK_WITH_MESSAGE, ['data' => [
                'containers' => count($containers),
                'activated_orders' => count($orders),
                'active_customers' => count($customers),
                'new_customers' => $newCustomers,
                'new_converted_customers' => $newConvertedCustomers,
                'total_customers' => CompanyModule::where('type', BusinessType::IMPORTER)->count(),
                'received_cbm' => $receivedCbm,
                'total_cbm' => $totalCbm,
                'daily_cbm' => $days ? (800 - $totalCbm) / $days : (800 - $totalCbm),
                'packages' => $packages->sum('quantity'),
                'total_orders' => Order::whereBetween('created_at', [$from, $to])->count()
            ]]))->handler();
    }

    public function profitModelReport(Request $request): JsonResponse {
        $from = $request->route('from') ? Carbon::parse($request->route('from')) : Carbon::now()->startOfMonth();
        $to = $request->route('to') ? Carbon::parse($request->route('to')) : Carbon::now()->endOfMonth();
        $model = (int) $request->route('model');
        $value = (float) $request->route('value');


        $containers = Container::whereBetween('loading_date', [$from, $to])->orderBy('loading_date')->get();

        $packages = $containers->flatMap(function ($container) {
            return $container->packages;
        });

        $totalCbm = $packages->sum(function($package){
            return (( (float) $package->width / 100) * ( (float) $package->length / 100) * ( (float) $package->height / 100)) * $package->quantity;
        });

        $projectedCbm = $packages->sum(function($package) use ($value, $model) {

            if($model === 2){
                return (( (float) ($package->width + ($package->width * ($value/100))) / 100) * ( (float) ($package->length + ($package->length * ($value/100))) / 100) * ( (float) ($package->height + ($package->height * ($value/100))) / 100)) * $package->quantity;
            }

            if($model === 3){
                return ((( (float) $package->width / 100) * ( (float) $package->length / 100) * ( (float) $package->height / 100)) + $value) * $package->quantity;
            }

            if($model === 4){
                $packageCbm = (( (float) $package->width / 100) * ( (float) $package->length / 100) * ( (float) $package->height / 100));
                return ( $packageCbm + ($packageCbm * ($value/100))) * $package->quantity;
            }

            return (( (float) ($package->width + $value) / 100) * ( (float) ($package->length + $value) / 100) * ( (float) ($package->height + $value) / 100)) * $package->quantity;

        });

        return (new ApiResponseObject('fetch monthly report Successful',
            '',
            HttpStatus::OK_WITH_MESSAGE, ['data' => [
                'total_cbm' => $totalCbm,
                'projected_cbm' => $projectedCbm,
            ]]))->handler();
    }

    public function customerReport(Request $request): JsonResponse {

        $connection = CompanyConnection::where('invitee_reference', $request->route('marking'))->firstOrFail();
        $id = $connection->invitee->id;

        $from = $request->route('from') ? Carbon::parse($request->route('from')) : Carbon::parse('01-01-2018');
        $to = $request->route('to') ? Carbon::parse($request->route('to')) : Carbon::now();

        $containers = Container::whereBetween('loading_date', [$from, $to])->orderBy('loading_date')->get();

        $packages = $containers->flatMap(function ($container) {
            return $container->packages;
        });

        $packages = $packages->filter(function($package) use ($id) {
            return $package->companyModule->id === $id;
        });

        $orders = $packages->unique(function ($package) {
            return $package->order;
        });

        $totalCbm = $packages->sum(function($package){
            return (( (float) $package->width / 100) * ( (float) $package->length / 100) * ( (float) $package->height / 100)) * $package->quantity;
        });

        return (new ApiResponseObject('fetch monthly report Successful',
            '',
            HttpStatus::OK_WITH_MESSAGE, ['data' => [
                'activated_orders' => count($orders),
                'total_cbm' => $totalCbm,
                'packages' => $packages->sum('quantity'),
            ]]))->handler();
    }

    public function serviceReport(Request $request): JsonResponse {

        return (new ApiResponseObject('fetch service report Successful',
            '',
            HttpStatus::OK_WITH_MESSAGE, ['data' => [
                'received' => (float) Package::warehouseReceiveList()->sum('quantity'),
                'pending_shipment' => (float) Package::shippingList()->whereDoesntHave('shippingSchedules', function($schedule){
                    return $schedule->dispatched()->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                })->sum('quantity'),
                'in_transit' => (float) Package::shippingList()->Shipping()->whereHas('shippingSchedules', function($schedule){
                    return $schedule->dispatched()->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                })->whereDoesntHave('container', function($container){
                    return $container->where('containers.status', ApprovalStatus::COMPLETED);
                })->sum('quantity'),
                'pending_delivery' => (float) Package::shippingList()->whereHas('container', function($container){
                    return $container->where('containers.status', ApprovalStatus::COMPLETED);
                })->whereDoesntHave('deliverySchedules', function($schedule){
                    return $schedule->dispatched()->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                })->sum('quantity'),
                'delivered' => (float) Package::shippingList()->whereHas('deliverySchedules', function($schedule){
                    return $schedule->dispatched()->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                })->sum('quantity'),
            ]]))->handler();
    }
}
