<?php

namespace App\Http\Controllers\Admin;

use App\Constants\Status;
use App\Http\Controllers\Controller;
use App\Lib\CurlRequest;
use App\Models\Admin;
use App\Models\AdminNotification;
use App\Models\SupportTicket;
use App\Models\SupportTicketReply;
use App\Rules\FileTypeValidate;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class AdminController extends Controller
{
    public function dashboard()
    {
        $pageTitle                       = 'Dashboard';
        $widget['open_ticket']           = SupportTicket::adminAccess()->open()->count();
        $widget['answered_ticket']       = SupportTicket::adminAccess()->answered()->count();
        $widget['customer_reply_ticket'] = SupportTicket::adminAccess()->customerReply()->count();
        $widget['closed_ticket']         = SupportTicket::adminAccess()->closed()->count();

        $agents = Admin::withCount(['supportTickets as answered_ticket_count' => function ($ticket) {
            $ticket->adminAccess()->answered();
        }, 'supportTickets as customer_reply_ticket_count' => function ($ticket) {
            $ticket->adminAccess()->customerReply();
        }])->orderBy('customer_reply_ticket_count', 'desc')->orderBy('answered_ticket_count', 'desc')->get();

        return view('admin.dashboard', compact('pageTitle', 'widget', 'agents'));
    }

    public function ticketInsight()
    {
        $duration = request()->duration;
        $range    = getDateRangeByKey($duration);

        $incoming = SupportTicketReply::where('admin_id', 0)->whereBetween('created_at', [$range['start'], $range['end']])
            ->whereHas('supportTicket', function ($ticket) {
                $ticket->adminAccess();
            })->selectRaw("DATE_FORMAT(created_at, '%d %M') as date, count(*) as total")
            ->groupBy('date')
            ->get();

        $outgoing = SupportTicketReply::where('admin_id', '>', 0)->whereBetween('created_at', [$range['start'], $range['end']])
            ->whereHas('supportTicket', function ($ticket) {
                $ticket->adminAccess();
            })->selectRaw("DATE_FORMAT(created_at, '%d %M') as date, count(*) as total")
            ->groupBy('date')
            ->get();

        $incomingDates = $incoming->pluck('date')->values();
        $outgoingDates = $outgoing->pluck('date')->values();

        $dates = $incomingDates->merge($outgoingDates)->unique();

        $dates = $dates->sortBy(function ($date) {
            return Carbon::createFromFormat('d F', $date);
        })->values();

        $result['keys'] = $dates;

        foreach ($dates as $date) {
            $incomingLog = $incoming->where('date', $date)->first();
            $outgoingLog = $outgoing->where('date', $date)->first();

            $result['incoming_data'][] = $incomingLog ? $incomingLog->total : 0;
            $result['outgoing_data'][] = $outgoingLog ? $outgoingLog->total : 0;
        }

        $result['total_incoming'] = array_sum($result['incoming_data'] ?? []);
        $result['total_outgoing'] = array_sum($result['outgoing_data'] ?? []);

        $result['total_tickets'] = SupportTicket::whereHas('replies', function ($reply) use ($range) {
            $reply->whereBetween('created_at', [$range['start'], $range['end']]);
        })->count();

        return $result;
    }

    public function customerHappinessRating()
    {
        $duration      = request()->duration;
        $range         = getDateRangeByKey($duration);
        $supportTicket = SupportTicket::adminAccess()->where('customer_happiness', '!=', null)
            ->whereBetween('rated_at', [$range['start'], $range['end']])
            ->selectRaw('count(*) as total, customer_happiness')
            ->groupBy('customer_happiness')
            ->get();

        $counts     = $supportTicket->pluck('total', 'customer_happiness');
        $greatCount = $counts->get('great', 0);
        $okayCount  = $counts->get('okay', 0);
        $badCount   = $counts->get('bad', 0);

        $totalCount = $greatCount + $okayCount + $badCount;

        $result['great_percentage'] = $greatCount ? showAmount($greatCount / $totalCount * 100) : 0;
        $result['okay_percentage']  = $okayCount ? showAmount($okayCount / $totalCount * 100) : 0;
        $result['bad_percentage']   = $badCount ? showAmount($badCount / $totalCount * 100) : 0;

        return $result;
    }

    public function departmentInsight()
    {
        $duration = request()->duration;
        $range    = getDateRangeByKey($duration);

        $incoming = SupportTicketReply::whereHas('supportTicket', function ($ticket) {
                $ticket->adminAccess();
            })->whereBetween('support_ticket_replies.created_at', [$range['start'], $range['end']])
            ->join('support_tickets', 'support_ticket_replies.support_ticket_id', '=', 'support_tickets.id')
            ->join('departments', 'support_tickets.department_id', '=', 'departments.id')
            ->where('support_ticket_replies.admin_id', 0)
            ->select([
                'support_tickets.department_id',
                'departments.name as department_name',
                \DB::raw('count(*) as total'),
            ])
            ->groupBy('support_tickets.department_id', 'departments.name')
            ->get();

        $outgoing = SupportTicketReply::whereHas('supportTicket', function ($ticket) {
                $ticket->adminAccess();
            })->whereBetween('support_ticket_replies.created_at', [$range['start'], $range['end']])
            ->join('support_tickets', 'support_ticket_replies.support_ticket_id', '=', 'support_tickets.id')
            ->join('departments', 'support_tickets.department_id', '=', 'departments.id')
            ->where('support_ticket_replies.admin_id', '>=', 0)
            ->select([
                'support_tickets.department_id',
                'departments.name as department_name',
                \DB::raw('count(*) as total'),
            ])
            ->groupBy('support_tickets.department_id', 'departments.name')
            ->get();

        $incoming = $incoming->mapWithKeys(function ($item) {
            return [$item->department_name => $item->total];
        });

        $outgoing = $outgoing->mapWithKeys(function ($item) {
            return [$item->department_name => $item->total];
        });

        $incomingDepartmentNames = $incoming->keys();
        $outgoingDepartmentNames = $outgoing->keys();

        $departmentNames = $incomingDepartmentNames->merge($outgoingDepartmentNames)->unique();

        $departmentNames = $departmentNames->sort()->values();
        $result['keys']  = $departmentNames;

        foreach ($departmentNames as $departmentName) {
            $incomingCount = $incoming->get($departmentName, 0);
            $outgoingCount = $outgoing->get($departmentName, 0);

            $result['incoming_data'][] = $incomingCount;
            $result['outgoing_data'][] = $outgoingCount;
        }

        return $result;
    }

    public function profile()
    {
        $pageTitle = 'Profile';
        $admin     = auth('admin')->user();
        return view('admin.setting.profile_setting.profile', compact('pageTitle', 'admin'));
    }

    public function profileUpdate(Request $request)
    {
        $request->validate([
            'name'   => 'required',
            'email'  => 'required|email',
            'mobile' => 'nullable|numeric',
            'image'  => ['nullable', 'image', new FileTypeValidate(['jpg', 'jpeg', 'png'])],
        ]);

        $user = auth('admin')->user();

        if ($request->hasFile('image')) {
            try {
                $old         = $user->image;
                $user->image = fileUploader($request->image, getFilePath('adminProfile'), getFileSize('adminProfile'), $old);
            } catch (\Exception $exp) {
                $notify[] = ['error', 'Couldn\'t upload your image'];
                return back()->withNotify($notify);
            }
        }

        $user->name   = $request->name;
        $user->email  = $request->email;
        $user->mobile = $request->mobile;
        $user->save();
        $notify[] = ['success', 'Profile updated successfully'];
        return to_route('admin.profile')->withNotify($notify);
    }

    public function password()
    {
        $pageTitle = 'Password Setting';
        $admin     = auth('admin')->user();
        return view('admin.setting.profile_setting.password', compact('pageTitle', 'admin'));
    }

    public function passwordUpdate(Request $request)
    {
        $request->validate([
            'old_password' => 'required',
            'password'     => 'required|min:5|confirmed',
        ]);

        $user = auth('admin')->user();
        if (!Hash::check($request->old_password, $user->password)) {
            $notify[] = ['error', 'Password doesn\'t match!!'];
            return back()->withNotify($notify);
        }
        $user->password = Hash::make($request->password);
        $user->save();
        $notify[] = ['success', 'Password changed successfully.'];
        return to_route('admin.password')->withNotify($notify);
    }

    public function notifications()
    {
        $notifications   = AdminNotification::orderBy('id', 'desc')->with('user')->paginate(getPaginate());
        $hasUnread       = AdminNotification::where('is_read', Status::NO)->exists();
        $hasNotification = AdminNotification::exists();
        $pageTitle       = 'Notifications';
        return view('admin.setting.notifications', compact('pageTitle', 'notifications', 'hasUnread', 'hasNotification'));
    }

    public function notificationRead($id)
    {
        $notification          = AdminNotification::findOrFail($id);
        $notification->is_read = Status::YES;
        $notification->save();

        $url = $notification->click_url;
        if ($url == '#') {
            $url = url()->previous();
        }
        return redirect($url);
    }

    public function requestReport()
    {
        $pageTitle            = 'Your Listed Report & Request';
        $arr['app_name']      = systemDetails()['name'];
        $arr['app_url']       = env('APP_URL');
        $arr['purchase_code'] = env('PURCHASECODE');
        $url                  = "https://license.viserlab.com/issue/get?" . http_build_query($arr);
        $response             = CurlRequest::curlContent($url);
        $response             = json_decode($response);
        if (!$response || !isset($response->status) || !isset($response->message)) {
            return to_route('admin.dashboard')->withErrors('Something went wrong');
        }
        if ($response->status == 'error') {
            return to_route('admin.dashboard')->withErrors($response->message);
        }
        $reports = $response->message[0];
        return view('admin.setting.reports', compact('reports', 'pageTitle'));
    }

    public function reportSubmit(Request $request)
    {
        $request->validate([
            'type'    => 'required|in:bug,feature',
            'message' => 'required',
        ]);
        $url = 'https://license.viserlab.com/issue/add';

        $arr['app_name']      = systemDetails()['name'];
        $arr['app_url']       = env('APP_URL');
        $arr['purchase_code'] = env('PURCHASECODE');
        $arr['req_type']      = $request->type;
        $arr['message']       = $request->message;
        $response             = CurlRequest::curlPostContent($url, $arr);
        $response             = json_decode($response);
        if (!$response || !isset($response->status) || !isset($response->message)) {
            return to_route('admin.dashboard')->withErrors('Something went wrong');
        }
        if ($response->status == 'error') {
            return back()->withErrors($response->message);
        }
        $notify[] = ['success', $response->message];
        return back()->withNotify($notify);
    }

    public function readAllNotification()
    {
        AdminNotification::where('is_read', Status::NO)->update([
            'is_read' => Status::YES,
        ]);
        $notify[] = ['success', 'Notifications read successfully'];
        return back()->withNotify($notify);
    }

    public function deleteAllNotification()
    {
        AdminNotification::truncate();
        $notify[] = ['success', 'Notifications deleted successfully'];
        return back()->withNotify($notify);
    }

    public function deleteSingleNotification($id)
    {
        AdminNotification::where('id', $id)->delete();
        $notify[] = ['success', 'Notification deleted successfully'];
        return back()->withNotify($notify);
    }

    public function downloadAttachment($fileHash)
    {
        $filePath  = decrypt($fileHash);
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        $title     = slug(gs('site_name')) . '- attachments.' . $extension;
        try {
            $mimetype = mime_content_type($filePath);
        } catch (\Exception $e) {
            $notify[] = ['error', 'File does not exists'];
            return back()->withNotify($notify);
        }
        header('Content-Disposition: attachment; filename="' . $title);
        header("Content-Type: " . $mimetype);
        return readfile($filePath);
    }

}
