<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ticket;
use App\Models\User;
use Symfony\Component\HttpFoundation\Response;
use App\Traits\ApiResponser;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Log;
use Auth;

class TicketsController extends Controller
{
    use ApiResponser;

    public function pushTicket(Request $request)
    {
        $username = $request->username;
        $password = $request->password;

        if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
            $user = User::find(auth()->user()->id);
            $ticket = new Ticket();
            $ticket->title = $request->title;
            $ticket->type = $request->type ?? 'ISSUE';
            switch ($request->title) {
                case 'Bulk Blast Alert':
                    $ticket->priority = 4;
                    break;
                default:
                    $ticket->priority = $request->priority ?? ($request->type == 'ISSUE' ? 1 : 2);
                    break;
            }
            $ticket->description = $request->description;
            $user->ticketscreated()->save($ticket);
            return $this->success(data: [], message: 'Ticket Created Successfully', code: Response::HTTP_OK);
        } else {
            return $this->error(message: 'User Authorization Failed', code: Response::HTTP_UNAUTHORIZED, data: []);
        }
    }
    public function now($timezone = null)
    {
        return Date::now($timezone);
    }

    public function getDuration($duration = null, $dates = [])
    {
        // Log::info(json_encode($duration));
        // Log::info(json_encode($dates));

        if ($duration !== 'custom') {
            switch ($duration) {
                case 'week':
                    return [$this->now()->startOfWeek()->format('Y-m-d H:i:s'), $this->now()->endOfWeek()->format('Y-m-d H:i:s')];
                    break;
                case 'month':
                    return [$this->now()->startOfMonth()->format('Y-m-d H:i:s'), $this->now()->endOfMonth()->format('Y-m-d H:i:s')];
                    break;
                case 'year':
                    return [$this->now()->startOfYear()->format('Y-m-d H:i:s'), $this->now()->endOfYear()->format('Y-m-d H:i:s')];
                    break;
                case 'day':
                default:
                    return [$this->now()->startOfDay()->format('Y-m-d H:i:s'), $this->now()->endOfDay()->format('Y-m-d H:i:s')];
                    break;
            }
        } else {
            return [$dates['start_date'] . ' 00:00:00', $dates['end_date'] . ' 23:59:59'];
        }
    }

    // public function allAlerts(Request $request){
    //     // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
    //     // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');
    //     $reqDuration = $request->duration;
    //     $dates = $request->only('start_date','end_date');
    //     $duration=$this->getDuration($reqDuration,$dates);
    //     // Log::info(json_encode($request->all()));
    //     // Log::info(json_encode($duration));
    //     // Log::info(Ticket::where('status','PENDING')->whereBetween('updated_at',$duration)->toSql());

    //     $tickets = [
    //         'pending'=>Ticket::where('status','PENDING')->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'opened'=>Ticket::where('status','OPENED')->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'closed'=>Ticket::where('status','CLOSED')->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'escalated'=>Ticket::where('status','ESCALATED')->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'validated'=>Ticket::where('status','VALIDATED')->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'critical'=>Ticket::where('priority',1)->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'major'=>Ticket::where('priority',2)->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'minor'=>Ticket::where('priority',3)->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //         'warning'=>Ticket::where('priority',4)->where('type','!=','ALERT')->whereBetween('updated_at',$duration)->count(),
    //     ];
    //     return $this->success(data:$tickets,message:'Data found',code:Response::HTTP_OK);
    // }
    public function allTickets(Request $request)
    {
        // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
        // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');
        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);
        // Log::info(json_encode($request->all()));
        Log::info(json_encode($duration));
        // Log::info(Ticket::where('status','PENDING')->whereBetween('updated_at',$duration)->toSql());

        $tickets = [
            'pending' => Ticket::where('status', 'PENDING')->where('type', '!=', 'ALERT')->whereBetween('created_at', $duration)->count(),
            'opened' => Ticket::where('status', 'OPENED')->where('type', '!=', 'ALERT')->whereBetween('updated_at', $duration)->count(),
            'closed' => Ticket::where('status', 'CLOSED')->where('type', '!=', 'ALERT')->whereBetween('updated_at', $duration)->count(),
            'escalated' => Ticket::where('status', 'ESCALATED')->where('type', '!=', 'ALERT')->whereBetween('escalated_at', $duration)->count(),
            'validated' => Ticket::where('status', 'VALIDATED')->where('type', '!=', 'ALERT')->whereBetween('validated_at', $duration)->count(),
            'critical' => Ticket::where('priority', 1)->where('status', 'PENDING')->where('type', '!=', 'ALERT')->whereBetween('created_at', $duration)->count(),
            'major' => Ticket::where('priority', 2)->where('type', '!=', 'ALERT')->where('status', 'PENDING')->whereBetween('created_at', $duration)->count(),
            'minor' => Ticket::where('priority', 3)->where('type', '!=', 'ALERT')->where('status', 'PENDING')->whereBetween('created_at', $duration)->count(),
            'warning' => Ticket::where('priority', 4)->where('type', '!=', 'ALERT')->where('status', 'PENDING')->whereBetween('created_at', $duration)->count(),
            'alerts' => Ticket::where('type', '=', 'ALERT')->whereBetween('created_at', $duration)->count(),
            'alerts_closed' => Ticket::where('status', 'CLOSED')->where('type', '=', 'ALERT')->whereBetween('updated_at', $duration)->count(),
            'alerts_pending' => Ticket::where('status', 'PENDING')->where('type', '=', 'ALERT')->whereBetween('updated_at', $duration)->count(),
        ];
        return $this->success(data: $tickets, message: 'Data found', code: Response::HTTP_OK);
    }

    public function allAlerts(Request $request)
    {
        // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
        // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');
        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);
        $alerts = Ticket::where('type', '=', 'ALERT')->whereBetween('created_at', $duration)
        // ->take(1000)
            ->get()
            ->sortByDesc('tickets.created_at')
            ->values();
        return $this->success(data: $alerts, message: 'Data found', code: Response::HTTP_OK);
    }

    public function allPending(Request $request)
    {
        // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
        // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');
        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);
        $pending = Ticket::where('status', 'PENDING')->where('type', '!=', 'ALERT')->whereBetween('created_at', $duration)->with('creator', 'opener', 'validator', 'assignedto', 'escalator', 'escalatedto', 'closedby')
        // ->take(200)
            ->get()
            ->sortByDesc('tickets.created_at')
            ->values();
        return $this->success(data: $pending, message: 'Data found', code: Response::HTTP_OK);
    }
    public function allOpened(Request $request)
    {
        // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
        // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');
        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);

        $opened = Ticket::where('status', 'OPENED')->where('type', '!=', 'ALERT')->whereBetween('updated_at', $duration)->with('creator', 'opener', 'validator', 'assignedto', 'escalator', 'escalatedto', 'closedby')
        // ->take(200)
            ->get()
            ->sortByDesc('tickets.updated_at')
            ->values();
        return $this->success(data: $opened, message: 'Data found', code: Response::HTTP_OK);
    }
    public function allEscalated(Request $request)
    {
        // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
        // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');
        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);

        $escalated = Ticket::where('status', 'ESCALATED')->where('type', '!=', 'ALERT')->whereBetween('created_at', $duration)->with('creator', 'opener', 'validator', 'assignedto', 'escalator', 'escalatedto', 'closedby')
        // ->take(200)
            ->get()
            ->sortByDesc('tickets.updated_at')
            ->values();
        return $this->success(data: $escalated, message: 'Data found', code: Response::HTTP_OK);
    }
    public function allClosed(Request $request)
    {
        // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
        // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');

        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);

        $closed = Ticket::where('status', 'CLOSED')->where('type', '!=', 'ALERT')->whereBetween('created_at', $duration)->with('creator', 'opener', 'validator', 'assignedto', 'escalator', 'escalatedto', 'closedby')
        // ->take(200)
            ->get()
            ->sortByDesc('tickets.created_at')
            ->values();
        return $this->success(data: $closed, message: 'Data found', code: Response::HTTP_OK);
    }
    public function allValidated(Request $request)
    {
        // $startDate = $request->start_date?$request->start_date.' 00:00:00': $this->now()->startOfDay()->format('Y-m-d H:i:s');
        // $endDate = $request->end_date?$request->end_date.' 23:59:59':$this->now()->endOfDay()->format('Y-m-d H:i:s');
        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);

        $validated = Ticket::where('status', 'VALIDATED')->where('type', '!=', 'ALERT')->whereBetween('updated_at', $duration)->with('creator', 'opener', 'validator', 'assignedto', 'escalator', 'escalatedto', 'closedby')
        // ->take(200)
            ->get()
            ->sortByDesc('tickets.created_at')
            ->values();
        return $this->success(data: $validated, message: 'Data found', code: Response::HTTP_OK);
    }

    public function createTicket(Request $request, $user_id)
    {
        $user = User::find($user_id);
        if (!empty($user)) {
            $ticket = new Ticket();
            $ticket->title = $request->title;
            $ticket->type = $request->type;
            $ticket->description = $request->description;
            $ticket->priority = $request->priority;
            $user->ticketscreated()->save($ticket);
            $ticket->assignedTo()->associate(User::find($request->assigned_to));
            $ticket->save();
            return $this->success(data: [], message: 'Ticket Created Successfully', code: Response::HTTP_OK);
        } else {
            return $this->error(message: 'Ticket Creator Not Found', code: Response::HTTP_FORBIDDEN, data: []);
        }
    }
    public function viewTicket(Request $request)
    {
        $ticket_id = $request->query('ticket_id');
        $ticket = Ticket::with('creator', 'opener', 'validator', 'assignedto', 'escalator', 'escalatedto', 'closedby')->find($ticket_id);
        if (!empty($ticket)) {
            return $this->success(data: $ticket, message: 'Ticket Created Successfully', code: Response::HTTP_OK);
        } else {
            return $this->error(message: 'Specified Ticket Not Found', code: Response::HTTP_NOT_FOUND, data: []);
        }
    }
    public function updateTicket(Request $request)
    {
        $user_id = $request->user_id;
        $ticket_id = $request->ticket_id;

        $user = User::find($user_id);
        $ticket = Ticket::find($ticket_id);

        if (!empty($user) && !empty($ticket) && ($user->id == $ticket->creator->id || in_array($user->role->id, [1, 5, 6]))) {
            $ticket->title = $request->title;
            $ticket->type = $request->type;
            $ticket->description = $request->description;
            $ticket->priority = $request->priority;
            $ticket->assigned_to = $request->assigned_to;
            $ticket->save();
            return $this->success(data: [], message: 'Ticket Updated Successfully', code: Response::HTTP_OK);
        } else {
            return $this->error(message: 'You cannot update this ticket', code: Response::HTTP_UNAUTHORIZED, data: []);
        }
    }
    public function closeTicket(Request $request)
    {
        $user_id = $request->user_id;
        $ticket_id = $request->ticket_id;
        $user = User::find($user_id);
        $ticket = Ticket::find($ticket_id);

        if (!empty($user) && !empty($ticket)) {
            // if($ticket->opener->id == $user->id){
            $ticket->closedby()->associate($user);
            $ticket->closed_at = date('Y-m-d H:i:s');
            $ticket->status = 'CLOSED';
            $ticket->closure_comment = (!empty($request->closure_comment)) ? $request->closure_comment : $ticket->closure_comment;
            $ticket->save();
            return $this->success(data: [], message: ' Ticket Closed Successfully', code: Response::HTTP_OK);
            // }else{
            //   return $this->error(message:'You cannot cannot this ticket',code:Response::HTTP_UNAUTHORIZED,data:[]);
            // }

        } else {
            return $this->error(message: 'Specified Ticket Not Found', code: Response::HTTP_NOT_FOUND, data: []);
        }
    }
    public function openTicket(Request $request)
    {
        $user_id = $request->user_id;
        $ticket_id = $request->ticket_id;
        $user = User::find($user_id);
        $ticket = Ticket::find($ticket_id);
        // return $this->success(data:['uid'=>$user_id,'tid'=>$ticket_id],message:' Ticket Opened Successfully',code:Response::HTTP_OK);

        if (!empty($user) && !empty($ticket)) {
            // if($ticket->assignedto?->id == $user->id || $ticket->escalatedto?->id == $user->id){
            $ticket->opener()->associate($user);
            $ticket->opened_at = date('Y-m-d H:i:s');
            $ticket->status = 'OPENED';
            // $ticke ->opened_comment = (!empty($request->opened_comment))?$request->opened_comment:$ticket->opened_comment;
            $ticket->save();
            return $this->success(data: $ticket->id, message: ' Ticket Opened Successfully', code: Response::HTTP_OK);
            // }else{
            //   return $this->error(message:'You cannot open this ticket',code:Response::HTTP_UNAUTHORIZED,data:[]);
            // }

        } else {
            return $this->error(message: 'Specified Ticket Not Found', code: Response::HTTP_NOT_FOUND, data: []);
        }
    }
    public function deleteTicket(Request $request)
    {
        $user_id = $request->user_id;
        $ticket_id = $request->ticket_id;
        $user = User::find($user_id);
        $ticket = Ticket::find($ticket_id);

        if (!empty($user) && !empty($ticket)) {
            if ($user->role?->id == 1 || $ticket->creator?->id == $user->id) {
                //Only admin and creator can delete
                $ticket->delete();
                return $this->success(data: [], message: ' Ticket Deleted Successfully', code: Response::HTTP_OK);
            } else {
                return $this->error(message: 'You cannot delete this ticket', code: Response::HTTP_UNAUTHORIZED, data: []);
            }
        } else {
            return $this->error(message: 'Specified Ticket Not Found', code: Response::HTTP_NOT_FOUND, data: []);
        }
    }
    public function escalateTicket(Request $request)
    {
        //set status to ESCALATED
        $escalator_id = $request->escalator_id;
        $receiver_id = $request->receiver_id;
        $ticket_id = $request->ticket_id;
        $escalator = User::find($escalator_id);
        $receiver = User::find($receiver_id);
        $ticket = Ticket::find($ticket_id);

        if (!empty($escalator) && !empty($ticket) && !empty($receiver)) {
            if ($receiver->id !== $escalator->id) {
                $ticket->escalator()->associate($escalator);
                $ticket->escalatedto()->associate($receiver);
                $ticket->escalated_at = date('Y-m-d H:i:s');
                $ticket->status = 'ESCALATED';
                $ticket->escalator_comment = $request->escalator_comment;
                $ticket->save();
                return $this->success(data: [], message: ' Ticket Escalated Successfully', code: Response::HTTP_OK);
            } else {
                return $this->error(message: 'You cannot escalate ticket to yourself', code: Response::HTTP_BAD_REQUEST, data: []);
            }
        } else {
            return $this->error(message: 'Specified Ticket Not Found', code: Response::HTTP_NOT_FOUND, data: []);
        }
    }
    public function validateTicket(Request $request)
    {
        $user_id = $request->user_id;
        $ticket_id = $request->ticket_id;
        $user = User::find($user_id);
        $ticket = Ticket::find($ticket_id);

        if (!empty($user) && !empty($ticket)) {
            if ($ticket->creator->id == $user->id || in_array($user->role->id, [1, 6])) {
                $ticket->validator()->associate($user);
                $ticket->validated_at = date('Y-m-d H:i:s');
                $ticket->validator_comment = $request->validator_comment;
                $ticket->status = 'VALIDATED';
                $ticket->save();
                return $this->success(data: [], message: ' Ticket Validated Successfully', code: Response::HTTP_OK);
            } else {
                return $this->error(message: 'You cannot validate this ticket', code: Response::HTTP_UNAUTHORIZED, data: []);
            }
        } else {
            return $this->error(message: 'Specified Ticket Not Found', code: Response::HTTP_NOT_FOUND, data: []);
        }
    }

    //////////////////////////////////////////
    //User specific query handlers
    public function myTickets(Request $request)
    {
        $user_id = $request->query('user_id');
        $user = User::find($user_id);
        if (!empty($user)) {
            $tickets = [
                'created' => $user->ticketscreated,
                'opened' => $user->ticketsopened,
                'picked' => $user->ticketspicked,
                'validated' => $user->ticketsvalidated,
                'assigned' => $user->ticketsassigned,
                'escalated' => $user->ticketsescalated,
                'escalated_to' => $user->ticketsescalated_to,
                'closed' => $user->ticketsclosed,
            ];
            return $this->success(data: $tickets, message: 'Found', code: Response::HTTP_OK);
        } else {
            return $this->error(message: 'User does not exist', code: Response::HTTP_NOT_FOUND, data: []);
        }
    }
    public function hisTickets(Request $request, $my_id)
    {
        $myself = User::find($my_id);
        $user_id = $request->query('user_id');
        if (!empty($myself) && in_array($myself->role_id, [1, 6])) {
            $user = User::find($user_id);
            if (!empty($user)) {
                $userdata = [
                    'user' => $user,
                    'tickets' => [
                        'created' => $user->ticketscreated()->count(),
                        'opened' => $user->ticketsopened()->count(),
                        // 'picked'=>$user->ticketspicked()->count(),
                        'validated' => $user->ticketsvalidated()->count(),
                        'assigned' => $user->ticketsassigned()->count(),
                        'escalated' => $user->ticketsescalated()->count(),
                        'escalated_to' => $user->ticketsescalated_to()->count(),
                        'closed' => $user->ticketsclosed()->count(),
                    ]
                ];
                return $this->success(data: $userdata, message: 'Found', code: Response::HTTP_OK);
            } else {
                return $this->error(message: 'User does not exist', code: Response::HTTP_NOT_FOUND, data: []);
            }
        } else {
            return $this->error(message: 'You are not permitted to view other users', code: Response::HTTP_UNAUTHORIZED, data: []);
        }
    }


    public function occurrenceTickets(Request $request)
    {
        // $ticketCounts = Ticket::select('description', Ticket::raw('COUNT(*) as count'))
        // ->groupBy('description')
        // ->get();
        // $ticketCounts = Ticket::query()->select('description', 'priority', Ticket::raw('COUNT(*) as count'))
        //     ->groupBy('description')
        //     ->distinct() // Ensure only distinct descriptions are selected
        //     ->orderBy('description') // Optional: Order the results by description
        //     ->get();

        $reqDuration = $request->duration;
        $dates = $request->only('start_date', 'end_date');
        $duration = $this->getDuration($reqDuration, $dates);

        $ticketCounts = Ticket::query()
            ->select('description', 'priority', Ticket::raw('COUNT(*) as count'))
            ->whereBetween('created_at', $duration)
            ->groupBy('description', 'priority') // Group by both description and priority
            ->orderBy('count','desc') // Optional: Order the results by description
            // ->take(1000)
            ->get();



        return $this->success(data: $ticketCounts, message: 'Data found', code: Response::HTTP_OK);
    }
}
