<?php

namespace App\Modules\Dashboard_v2\controllers\api\v1;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\App;
use App\Models\User;
use Illuminate\Support\Facades\Config;
use App\Modules\Bookings\Task;
use App\Modules\Bookings\Repair;
use App\Modules\Bookings\Support;
use App\Modules\Bookings\Onsite;
use App\Modules\Bookings\Order;
use App\Modules\Bookings\Rma;
use App\Modules\Bookings\Project;
use App\Modules\Bookings\SaleLead;
use App\Modules\Bookings\Comment;
use App\Modules\Bookings\Targets\RepairsTarget;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Carbon\Carbon;

class DashboardControllerREST extends BaseController
{
    public function getSummary($id, Request $request)
    {
        $user = User::find($id);

        $data = [
            'repairs'  => intval(Repair::repairs()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', $id)->count()),
            'support'  => intval(Support::support()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', $id)->count()),
            'onsite'   => intval(Onsite::onsite()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', $id)->count()),
            'comments' => intval(Comment::thisMonth($request->input('start_date'), $request->input('end_date'))->where('created_by', $id)->count()),
            'bookings' => intval(Task::where('created_by', $id)->createdThisMonth($request->input('start_date'), $request->input('end_date'))->count()),
            'answered' => 0,
            'feedback' => floatval($user->feedback),
            'targets'  => [
                'repairs' => RepairsTarget::user($user)->startDate($request->input('start_date'))->endDate($request->input('end_date'))->toArray(),
            ],
        ];

        return $data;
    }

    public function getTasks(Request $request)
    {
        // This is a batch call that retrieve all the items for the my tasks
        $batch = [
            'own'      => json_decode(App::make('App\Modules\Bookings\TaskControllerREST')->index(['user_id'       => $request->input('user_id'), 'results' => 'own', 'client' => true, 'creator' => true, 'limit' => 100, 'page' => $request->input('page', 1)])->getContent()),
            'delivery' => json_decode(App::make('App\Modules\Bookings\DeliveryControllerRESTv1')->index(['user_id' => $request->input('user_id'), 'results' => 'own', 'client' => true, 'completed' => true])->getContent()),
            'messages' => json_decode(App::make('App\Modules\Bookings\MessageControllerRESTv1')->index(['user_id'  => $request->input('user_id'), 'results' => 'open', 'client' => true])->getContent()),
            'projects' => json_decode(App::make('App\Modules\Bookings\ProjectControllerRESTv1')->index(['user_id'  => $request->input('user_id'), 'results' => 'own', 'client' => true])->getContent()),
        ];

        // Other solution:
        // $request = Request::create('api/items', 'GET', $params);
        // return Route::dispatch($request)->getContent();

        return $batch;
    }

    public function getStats(Request $request)
    {
        $data = [
            'repairs' => [
                'completed' => Repair::repairs()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)->count(),
                'returns'   => Repair::where('tasks.type', 'repair')->join('tasks as a', 'tasks.id', '=', 'a.return_id')->thisMonth($request->input('start_date'), $request->input('end_date'))->where('a.completed', 1)->where('a.assigned_to', Auth::user()->id)->whereNotNull('tasks.return_id')->count(),
                /*
                'labour'    => Repair::repairs()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)->sum('labour'),
                'booking_fees' => Repair::repairs()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)->whereNotNull('booking_fee_id')->count() * Config::get('settings.booking_fee'),
                'parts'     => Repair::leftJoin('parts', function($join)
                        {
                            return $join->on('parts.related_id', '=', 'tasks.id')->where('parts.related_type', '=', 'task');
                        })
                        ->repairs()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)
                        ->select(\DB::raw('SUM(parts.quantity * parts.price * (parts.vat / 100 + 1)) as parts'))->first()->parts,
                */
            ],
            'support' => [
                'completed' => Support::support()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)->count(),
                /*
                'labour'    => Support::support()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)->sum('labour'),
                'parts'     => Support::leftJoin('parts', function($join)
                        {
                            return $join->on('parts.related_id', '=', 'tasks.id')->where('parts.related_type', '=', 'task');
                        })
                        ->support()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)
                        ->select(\DB::raw('SUM(parts.quantity * parts.price * (parts.vat / 100 + 1)) as parts'))->first()->parts,
                */
            ],
            'onsite' => [
                'completed' => Onsite::onsite()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)->count(),
                /*
                'labour'    => Onsite::onsite()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)->sum('labour'),
                'parts'     => Onsite::leftJoin('parts', function($join)
                        {
                            return $join->on('parts.related_id', '=', 'tasks.id')->where('parts.related_type', '=', 'task');
                        })
                        ->onsite()->thisMonth($request->input('start_date'), $request->input('end_date'))->completed()->where('assigned_to', Auth::user()->id)
                        ->select(\DB::raw('SUM(parts.quantity * parts.price * (parts.vat / 100 + 1)) as parts'))->first()->parts,
                */
            ],
        ];

        return $data;
    }

    public function getRepairsLeaderboard(Request $request)
    {
        $users = User::getActiveList()->reject(function($user) {
            return $user->repair_target === null;
        })->values();

        return $users->map(function($user) use ($request) {
            return [
                'id'      => $user->id,
                'name'    => $user->name,
                'targets' => RepairsTarget::user($user)->startDate($request->input('start_date'))->endDate($request->input('end_date'))->toArray(),
            ];
        })->sortByDesc('targets.total')->values();
    }

    public function getPieChartStats(Request $request)
    {
        $startDate = $request->input('start_date');
        $endDate = $request->input('end_date');
        
        // Get all data in optimized queries with proper indexes
        $data = [
            'repairs' => Repair::select(DB::raw('SUM(`labour`) as labour, assigned_to'))->repairs()->thisMonth($startDate, $endDate)->completed()->whereNotNull('assigned_to')->groupBy('assigned_to')->with('user')->get(),
            'support' => Support::select(DB::raw('COUNT(`id`) as cnt, assigned_to'))->support()->thisMonth($startDate, $endDate)->completed()->whereNotNull('assigned_to')->groupBy('assigned_to')->with('user')->get(),
            'onsite'  => Onsite::select(DB::raw('SUM(`labour`) as labour, COUNT(`id`) as cnt, assigned_to'))->onsite()->thisMonth($startDate, $endDate)->completed()->whereNotNull('assigned_to')->groupBy('assigned_to')->with('user')->get(),
        ];

        // Optimize booking fees calculation - single query instead of N queries
        if (!empty($data['repairs'])) {
            $assignedUserIds = $data['repairs']->pluck('assigned_to')->toArray();
            
            $bookingFees = Repair::select(DB::raw('COUNT(*) as cnt, assigned_to'))
                ->repairs()
                ->thisMonth($startDate, $endDate)
                ->completed()
                ->whereIn('assigned_to', $assignedUserIds)
                ->whereNotNull('booking_fee_id')
                ->groupBy('assigned_to')
                ->pluck('cnt', 'assigned_to');
                
            $bookingFeeAmount = \Config::get('settings.booking_fee');
            
            foreach ($data['repairs'] as $value) {
                $value->fees = ($bookingFees[$value->assigned_to] ?? 0) * $bookingFeeAmount;
            }
        }

        return $data;
    }

    public function getRepairsSummary(Request $request)
    {
        $data = [
            'assigned' => [
                'user'        => Repair::repairs()->where('completed', 0)->where('assigned_to', $request->input('user_id', Auth::user()->id))->count(),
                'technicians' => Repair::repairs()->where('completed', 0)->whereNotNull('assigned_to')->count(),
            ],
            'queue'  => [
                'count'   => Repair::repairs()->where('completed', 0)->whereNull('assigned_to')->count(),
                'prebook' => Repair::repairs()->where('completed', 0)->whereNull('assigned_to')->where('prebook', 1)->count(),
            ],
        ];

        return $data;
    }

    public function getSupportSummary(Request $request)
    {
        $data = [
            'assigned' => [
                'user'        => Support::support()->where('completed', 0)->where('assigned_to', $request->input('user_id', Auth::user()->id))->count(),
                'technicians' => Support::support()->where('completed', 0)->whereNotNull('assigned_to')->count(),
            ],
            'queue'  => [
                'count' => Support::support()->where('completed', 0)->whereNull('assigned_to')->count(),
            ],
        ];

        return $data;
    }

    public function getOnsiteSummary(Request $request)
    {
        $data = [
            'assigned' => [
                'user'        => Onsite::onsite()->where('completed', 0)->where('assigned_to', $request->input('user_id', Auth::user()->id))->count(),
                'technicians' => Onsite::onsite()->where('completed', 0)->whereNotNull('assigned_to')->count(),
            ],
            'queue'  => [
                'count' => Onsite::onsite()->where('completed', 0)->whereNull('assigned_to')->count(),
            ],
        ];

        return $data;
    }

    public function getCompletedSummary(Request $request)
    {
        $data = [
            'completed' => Task::where('completed', 1)->where('assigned_to', $request->input('user_id', Auth::user()->id))->where('completed_at', '>=',  Carbon::now()->addMonths(-1))->where('completed_at', '<=',  Carbon::now())->get(),
        ];

        return $data;
    }

    public function getOrdersSummary(Request $request)
    {
        $data = [
            'assigned' => [
                'user'        => Order::orders()->where('completed', 0)->where('assigned_to', $request->input('user_id', Auth::user()->id))->count(),
                'technicians' => Order::orders()->where('completed', 0)->whereNotNull('assigned_to')->count(),
            ],
            'queue'  => [
                'count' => Order::orders()->where('completed', 0)->whereNull('assigned_to')->count(),
            ],
        ];

        return $data;
    }

    public function getRmaSummary(Request $request)
    {
        $data = [
            'assigned' => [
                'user'        => Rma::rma()->where('completed', 0)->where('assigned_to', $request->input('user_id', Auth::user()->id))->count(),
                'technicians' => Rma::rma()->where('completed', 0)->whereNotNull('assigned_to')->count(),
            ],
            'queue'  => [
                'count' => Rma::rma()->where('completed', 0)->whereNull('assigned_to')->count(),
            ],
        ];

        return $data;
    }

    public function getProjectsSummary(Request $request)
    {
        $data = [
            'assigned' => [
                'user'        => Project::where('completed', 0)->where('assigned_to', $request->input('user_id', Auth::user()->id))->count(),
                'technicians' => Project::where('completed', 0)->whereNotNull('assigned_to')->count(),
            ],
            'queue'  => [
                'count' => Project::where('completed', 0)->whereNull('assigned_to')->count(),
            ],
        ];

        return $data;
    }

    public function getSaleLeadSummary(Request $request)
    {
        $data = [
            'assigned' => [
                'user'        => SaleLead::saleLeads()->where('completed', 0)->where('assigned_to', $request->input('user_id', Auth::user()->id))->count(),
                'technicians' => SaleLead::saleLeads()->where('completed', 0)->whereNotNull('assigned_to')->count(),
            ],
            'queue'  => [
                'count' => SaleLead::saleLeads()->where('completed', 0)->whereNull('assigned_to')->count(),
            ],
        ];

        return $data;
    }
}
