<?php

namespace App\Services;

use App\Models\Module;
use App\Models\Resource;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;

class ReportService
{
    private $moduleService;
    private $groupService;
    private $categoryService;

    public function __construct(
        ModuleService $moduleService,
        GroupService $groupService,
        CategoryService $categoryService
    ) {
        $this->moduleService   = $moduleService;
        $this->groupService    = $groupService;
        $this->categoryService = $categoryService;
    }

    public function getReports()
    {

        if (auth()->user()->isAdminOrOwner()) {
            $reports = $this->replaceReportCreator($this->getAllReports());
            return $reports;
        } else {
            $reports = $this->replaceReportCreator($this->getAuthedUserReports());
            return $reports;
        }

    }

    public function getAllReports()
    {
        return Resource::whereHas('module', function ($q) {

            return $q->where('name', 'Reports');
        })->orWhereHas('module.parent', function ($q) {
            return $q->where('name', 'Reports');
        })
            ->with('category')
            ->orderByDesc('created_at')
            ->get();
    }

    public function getAuthedUserReports()
    {
        $prefix = config("srm_config.installer.table_prefix", "srm_");

        return Resource::where(function ($q) use ($prefix) {
            $q->where(function ($q) {
                $q->whereHas('module', function ($q) {
                    return $q->where('name', 'Reports');
                })->orWhereHas('module.parent', function ($q) {
                    return $q->where('name', 'Reports');
                });
            })->where(function ($q) use ($prefix) {
                $q->whereHas('resource_permissions', function ($q) use ($prefix) {
                    return $q->where($prefix . 'resource_permissions.group_id', auth()->user()->group_id);
                })->orWhere(function ($q) {
                    $q->where('access_control_type', 'Public');
                });
                // ->orWhere('resource_creator', auth()->id());
            });
        })
            ->with('category')
            ->orderByDesc('created_at')
            ->get();
    }

    public function changeReportCategory($report, $data)
    {
        $this->checkReportCreatorPermission($report);

        $report->category_id = $data['report_category'];
        $report->save();
    }

    public function show($report)
    {

        switch (strtolower($report->module->name)) {
            case strtolower('Blank Reports'):
                $this->checkReportAccessPermission($report);
                $this->checkReportExists($report);
                return $report;
                break;
            default:
                abort(Response::HTTP_FORBIDDEN, "You don't have permission to access this report");
                break;
        }

    }

    public function create()
    {

        if (
            !$this->moduleService->checkCurrentUserGroupCanCreateModule('Reports')
            && !auth()->user()->isAdminOrOwner()
        ) {
            abort(403, trans('report.permission_denied'));
        }

        // $this->checkThereIsGroupsAndCategories();

        $this->createReportSession();

        if (!$this->moduleService->checkModuleOnlyActiveInChildren('Reports', 'Blank Reports')) {
            return "";
        } else {
            return "SRM9/SRM/wizard";
        }

    }

    public function edit(Resource $report)
    {

        $this->checkReportCreatorPermission($report);

        // $this->checkThereIsGroupsAndCategories();

        $this->editReportSession($report);

        switch (strtolower($report->module->name)) {
            case 'blank reports':
                return "SRM9/SRM/wizard";
                break;
            default:
                return "";
                break;
        }

    }

    public function destroy($report)
    {
        $this->checkReportCreatorPermission($report);
        $this->checkScheduledReportExists($report);

        try {
            $this->deleteReportFolder($report);
        } catch (\Exception $e) {
            abort(400, trans('report.delete_error'));
        }

        $report->forceDelete();
    }

    private function checkScheduledReportExists($report)
    {

        if ($report->scheduledTaskResource()->exists()) {
            abort(400, trans('report.delete_scheduled_task_before_error', [
                'report'        => $report->name,
                'scheduledTask' => $report->scheduledTaskResource()->first()->scheduledTask()->first()->title
            ]));
        }

    }

    private function checkReportCreatorPermission(Resource $report)
    {

        if (
            !(auth()->user()->isAdminOrOwner() ||
                $report->resource_creator === auth()->user()->user_ID)
        ) {
            abort(403, trans('report.unauthorized'));
        }

    }

    private function checkReportAccessPermission(Resource $report)
    {

        if (
            !(auth()->user()->isAdminOrOwner() || strtolower($report->access_control_type) == "public" ||
                in_array(auth()->user()->group_id, $report->resource_permissions->pluck("group_ID")->toArray()))

        ) {
            abort(403, trans('report.access_unautorized'));
        }

    }

    private function checkReportExists(Resource $report)
    {

        if (!File::exists(public_path() . "/srm_modules/" . $report->url)) {
            abort(404, "Report Not Found");
        }

    }

    public function checkThereIsGroupsAndCategories()
    {

        if ($this->categoryService->getCategoriesCount() == 0 || $this->groupService->getGroupsCount() == 0) {
            abort(400, trans('report.create_group_and_category'));
        }

    }

    private function createReportSession()
    {
        $_SESSION["srm_wizard_config"]["edit_mode"] = false;
    }

    private function editReportSession($report)
    {
        $_SESSION["srm_wizard_config"]["edit_mode"] = 1;
        $_SESSION["srm_wizard_config"]["report_id"] = $report->id;
    }

    private function deleteReportFolder($report)
    {
        Storage::disk('reports')->deleteDirectory(
            dirname($report->url)
        );
    }

    private function replaceReportCreator($reports)
    {

        if (checkDemo()) {

            $userIdentifiers = [];
            $userCounter     = 1;

            foreach ($reports as $report) {

                if (isset($report->creator)) {
                    $creatorName = $report->creator->user_name;

                    if (!isset($userIdentifiers[$creatorName])) {
                        $userIdentifiers[$creatorName] = '<user ' . $userCounter . '>';
                        $userCounter++;
                    }

                    $report->report_creator = $userIdentifiers[$creatorName];
                } else {
                    $report->report_creator = '';
                }

            }

        }

        return $reports;
    }

}
