<?php

namespace App\Http\Controllers\Admin;

use App\Constants\Status;
use App\Http\Controllers\Controller;
use App\Lib\FormProcessor;
use App\Models\ApplyService;
use App\Models\GeneralSetting;
use App\Models\Service;
use App\Models\ServiceCategory;
use App\Models\Transaction;
use App\Models\User;
use Illuminate\Http\Request;

class ServiceController extends Controller {

    public function categoryService() {
        $pageTitle  = 'Service category';
        $categories = ServiceCategory::searchable(['name', 'field_name'])->latest()->paginate(getPaginate());
        return view('admin.service.category', compact('pageTitle', 'categories'));
    }

    public function categoryServiceStore(Request $request) {

        $request->validate([
            'name'       => 'required|max:191|unique:service_categories',
            'field_name' => 'sometimes|max:91',
        ]);

        $field_name = $request->field_name;

        $newCategory       = new ServiceCategory();
        $newCategory->name = $request->name;

        if ($field_name) {
            $newCategory->field_type = 'select';
            $newCategory->field_name = str_replace(' ', '_', strtolower($field_name));
        }

        $newCategory->save();

        $notify[] = ['success', 'Service category added successfully'];
        return back()->withNotify($notify);
    }

    public function categoryServiceUpdate(Request $request) {

        $request->validate([
            'id'         => 'required|exists:service_categories',
            'name'       => 'required|max:40|unique:service_categories,id',
            'field_name' => 'sometimes|max:40',
        ]);

        $field_name = $request->field_name;

        $findCategory       = ServiceCategory::find($request->id);
        $findCategory->name = $request->name;

        if ($field_name) {
            $findCategory->field_type = 'select';
            $findCategory->field_name = str_replace(' ', '_', strtolower($field_name));
        } else {
            $findCategory->field_type = null;
            $findCategory->field_name = null;
        }

        $findCategory->save();

        $notify[] = ['success', 'Service category info updated successfully'];
        return back()->withNotify($notify);
    }

    public function categoryServiceStatus($id) {
        return ServiceCategory::changeStatus($id);
    }

    public function service() {
        $pageTitle = 'Services';
        $services  = Service::searchable(['name', 'category:name'])->latest()->paginate(getPaginate());
        return view('admin.service.index', compact('pageTitle', 'services'));
    }

    public function createServicePage() {
        $pageTitle  = 'Create Service';
        $categories = ServiceCategory::where('status', 1)->latest()->get();
        return view('admin.service.create', compact('pageTitle', 'categories'));
    }

    public function serviceStore(Request $request) {

        $validation = [
            'delay'          => 'required|max:91',
            'category_id'    => 'required|exists:service_categories,id',
            'fixed_charge'   => 'required|numeric|gte:0',
            'percent_charge' => 'required|numeric|gte:0',
            'name'           => 'required|string|max:250',
            'icon'           => 'required|string|max:250',
            'field_name.*'   => 'required',
            'type.*'         => 'required|in:text,textarea,file',
            'validation.*'   => 'required|in:required,nullable',
        ];

        $formProcessor       = new FormProcessor();
        $generatorValidation = $formProcessor->generatorValidation();
        $validation          = array_merge($validation, $generatorValidation['rules']);
        $request->validate($validation, $generatorValidation['messages']);
        $generate = $formProcessor->generate('service');

        $category = ServiceCategory::where('id', $request->category_id)->where('status', 1)->firstOrFail();

        if ($category->field_type) {

            if (!$request->has('select')) {
                $notify[] = ['error', str_replace('_', ' ', ucfirst($category->field_name)) . ' field is required'];
                return back()->withNotify($notify);
            } else {
                $select                                                           = array();
                $select[str_replace(' ', '_', strtolower($category->field_name))] = $request->select;
            }
        }

        $newService                 = new Service();
        $newService->name           = $request->name;
        $newService->icon           = $request->icon;
        $newService->category_id    = $request->category_id;
        $newService->delay          = $request->delay;
        $newService->select_field   = $request->has('select') == true ? json_encode($select) : null;
        $newService->fixed_charge   = $request->fixed_charge;
        $newService->percent_charge = $request->percent_charge;
        $newService->description    = $request->description;
        $newService->form_id        = @$generate->id ?? 0;
        $newService->save();

        $notify[] = ['success', 'Service added successfully'];
        return back()->withNotify($notify);
    }

    public function serviceUpdatePage($id) {

        $service    = Service::findOrFail($id);
        $form       = $service->form;
        $pageTitle  = 'Update Service';
        $categories = ServiceCategory::active()->latest()->get();

        $array  = $service->select_field == true ? (array) json_decode($service->select_field) : null;
        $type   = gettype($array);
        $label  = $type == 'array' ? array_keys($array) : null;
        $label  = $type == 'array' ? implode(" ", $label) : null;
        $values = $type == 'array' ? $array[$label] : null;

        return view('admin.service.edit', compact('pageTitle', 'service', 'categories', 'array', 'type', 'label', 'values', 'form'));
    }

    public function serviceUpdate(Request $request) {
        $validation = [
            'id'             => 'required|exists:services,id',
            'delay'          => 'required|max:91',
            'category_id'    => 'required|exists:service_categories,id',
            'fixed_charge'   => 'required|numeric|gte:0',
            'percent_charge' => 'required|numeric|gte:0',
            'name'           => 'required|string|max:250',
            'icon'           => 'required|string|max:250',
        ];

        $formProcessor       = new FormProcessor();
        $generatorValidation = $formProcessor->generatorValidation();
        $validation          = array_merge($validation, $generatorValidation['rules']);
        $request->validate($validation, $generatorValidation['messages']);

        $category = ServiceCategory::where('id', $request->category_id)->where('status', 1)->firstOrFail();

        if ($category->field_type) {

            if (!$request->has('select')) {
                $notify[] = ['error', str_replace('_', ' ', ucfirst($category->field_name)) . ' field is required'];
                return back()->withNotify($notify);
            } else {
                $select                                                           = array();
                $select[str_replace(' ', '_', strtolower($category->field_name))] = $request->select;
            }
        }

        $findService                 = Service::find($request->id);
        $findService->name           = $request->name;
        $findService->icon           = $request->icon;
        $findService->category_id    = $request->category_id;
        $findService->delay          = $request->delay;
        $findService->select_field   = $request->has('select') == true ? json_encode($select) : null;
        $findService->fixed_charge   = $request->fixed_charge;
        $findService->percent_charge = $request->percent_charge;
        $findService->description    = $request->description;

        $generate             = $formProcessor->generate('service', true, 'id', $findService->form_id);
        $findService->form_id = @$generate->id ?? 0;

        $findService->save();

        $notify[] = ['success', 'Service info updated successfully'];
        return back()->withNotify($notify);
    }

    public function status($id) {
        return Service::changeStatus($id);
    }

    public function pendingService() {
        $pageTitle = 'Pending Services';
        $services  = ApplyService::searchable(['user:username', 'service:name', 'service.category:name'])->where('status', Status::DATA_PENDING)->latest()->paginate(getPaginate());
        return view('admin.applied.showServices', compact('pageTitle', 'services'));
    }

    public function serviceDetails($id) {
        $service   = ApplyService::where('id', $id)->where('status', '!=', Status::DATA_INSERTED)->firstOrFail();
        $pageTitle = @$service->user->fullname . ' requested for ' . @$service->service->category->name;
        return view('admin.applied.details', compact('pageTitle', 'service'));
    }

    public function serviceApprove($id) {
        $service = ApplyService::where('id', $id)->where('status', Status::DATA_PENDING)->firstOrFail();
        $user    = User::find($service->user_id);

        $service->status         = Status::DATA_APPROVED;
        $service->admin_feedback = 'Approved';
        $service->save();

        $general = GeneralSetting::first();

        notify($user, 'SERVICE_APPROVE', [
            'amount'         => $service->amount,
            'charge'         => $service->total_charge,
            'currency'       => $general->cur_text,
            'service_name'   => $service->service->category->name,
            'admin_feedback' => 'Approved',

        ]);

        $notify[] = ['success', 'Requested service approved successfully'];
        return redirect()->route('admin.applied.pending.service')->withNotify($notify);
    }

    public function serviceReject(Request $request) {

        $request->validate([
            'id'      => 'required|exists:apply_services,id',
            'message' => 'required|max:1000',

        ]);

        $service = ApplyService::where('id', $request->id)->where('status', Status::DATA_PENDING)->firstOrFail();

        $user = User::find($service->user_id);
        $user->balance += $service->after_charge;
        $user->save();

        $service->admin_feedback = $request->message;
        $service->status         = 3;
        $service->save();

        $general = GeneralSetting::first();

        $transaction               = new Transaction();
        $transaction->user_id      = $user->id;
        $transaction->amount       = getAmount($service->after_charge);
        $transaction->post_balance = getAmount($user->balance);
        $transaction->charge       = 00;
        $transaction->trx_type     = '+';
        $transaction->details      = 'Service request has been rejected and refund money';
        $transaction->trx          = getTrx();
        $transaction->remark       = 'service_rejected';
        $transaction->save();

        notify($user, 'SERVICE_REJECTED', [
            'trx'          => $transaction->trx,
            'amount'       => $service->amount,
            'charge'       => $service->total_charge,
            'currency'     => $general->cur_text,
            'post_balance' => $user->balance,
            'service_name' => $service->service->category->name,
            'reason'       => $service->admin_feedback,
        ]);

        $notify[] = ['success', 'Requested service canceled successfully'];
        return redirect()->route('admin.applied.pending.service')->withNotify($notify);
    }

    public function serviceApproved() {
        $pageTitle = 'Approved Services';
        $services  = ApplyService::searchable(['user:username', 'service:name', 'service.category:name'])->where('status', Status::DATA_APPROVED)->latest()->paginate(getPaginate());

        return view('admin.applied.showServices', compact('pageTitle', 'services'));
    }

    public function serviceCanceled() {
        $pageTitle = 'Rejected Services';
        $services  = ApplyService::searchable(['user:username', 'service:name', 'service.category:name'])->where('status', Status::DATA_REJECTED)->latest()->paginate(getPaginate());
        return view('admin.applied.showServices', compact('pageTitle', 'services'));
    }
    public function serviceAll() {
        $pageTitle = 'All Services';
        $services  = ApplyService::where('status', '!=', Status::DATA_INSERTED)->latest()->paginate(getPaginate());
        return view('admin.applied.showServices', compact('pageTitle', 'services'));
    }
}
