<?php

namespace App\Http\Controllers\AccessManagement\GroupManagement;

use Activity;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Models\AccessManagement\GroupManagement\Role;
use App\Models\User;
use App\Traits\Logs\HasCustomLogs;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Suiterus\Dms\Enums\Log\GroupLogType;
use Suiterus\Dms\Models\Repositories\Section;
use Suiterus\Dms\Models\Repositories\SectionAccess;

class SectionAccessController extends Controller
{

    use HasCustomLogs;

    public function createSectionAccessGroup(Request $request)
    {
        $valid = Validator::make($request->all(), [
            'section_accesses' => 'array'
        ]);

        if ($valid->fails()) {
            return response()->json([
                'message' => $valid->errors()
            ]);
        } else {
            DB::beginTransaction();
            try {

                foreach ($request->section_accesses as $section_access) {
                    $valid = Validator::make($section_access, [
                        'role_id' => 'required|exists:' . env('DB_CONNECTION') . '.roles,id',
                        'section_id' => 'required|exists:' . env('DMS_DB_CONNECTION') . '.sections,id'
                    ]);
                    if ($valid->fails()) {
                        return response()->json([
                            'message' => $valid->errors()
                        ]);
                    }

                    $isExist = SectionAccess::where([
                        ['section_id', $section_access['section_id']],
                        ['group_id', $section_access['role_id']],
                    ])->first();

                    if (!$isExist) {
                        $sectionAccess = SectionAccess::create(
                            [
                                'section_id' => $section_access['section_id'],
                                'group_id' => $section_access['role_id'],
                                'user_id' => 0,
                                'access_level' => 2,
                                'shared_by' => Auth::id(),
                                'shared_date' => now()
                            ]
                        );

                        $sectionAccess = SectionAccess::with(['section' => function ($query) {
                            $query->without(['author']);
                        }])->without([
                            'user',
                        ])->find($sectionAccess->id);

                        $this->logCustomMessage(
                            'add_group_folder',
                            $sectionAccess,
                            Auth::user()->name . ' added a folder ' . $sectionAccess->section->name . ' to the group ' . $sectionAccess->group->name,
                            $sectionAccess,
                            GroupLogType::ADD_GROUP_FOLDER,
                            new Activity()
                        );
                    }
                }

                foreach ($request->removed_section_accesses as $section_access) {
                    $valid = Validator::make($section_access, [
                        'role_id' => 'required|exists:' . env('DB_CONNECTION') . '.roles,id',
                        'section_id' => 'required|exists:' . env('DMS_DB_CONNECTION') . '.sections,id'
                    ]);
                    if ($valid->fails()) {
                        return response()->json([
                            'message' => $valid->errors()
                        ]);
                    }

                    $where = [
                        ['section_id', $section_access['section_id']],
                        ['group_id', $section_access['role_id']],
                    ];

                    $deletedSectionAccess = SectionAccess::where($where)->with(['section' => function ($query) {
                        $query->without(['author']);
                    }])->without([
                        'user',
                    ])->first();

                    SectionAccess::where($where)->delete();

                    $this->logCustomMessage(
                        'remove_group_folder',
                        $deletedSectionAccess,
                        Auth::user()->name . ' removed a folder ' . $deletedSectionAccess->section->name . ' to the group ' . $deletedSectionAccess->group->name,
                        $deletedSectionAccess,
                        GroupLogType::REMOVE_GROUP_FOLDER,
                        new Activity()
                    );
                }

                DB::commit();
                return response()->json([
                    'text'  =>  'Role leader has been created.'
                ]);
            } catch (Exception $e) {
                DB::rollback();
                return response()->json([
                    'errors'    =>  ['There is a problem in creating role leader.'],
                    'msg'       =>  $e->getMessage()
                ], 500);
            }
        }
    }

    public function create(Request $request)
    {

        $valid = Validator::make($request->all(), [
            'section_id' => 'required|exists:' . env('DMS_DB_CONNECTION') . '.sections,id'
        ]);

        if ($valid->fails()) {
            return response()->json([
                'message' => $valid->errors()
            ], 400);
        }

        DB::connection(env('DMS_DB_CONNECTION'))->beginTransaction();
        try {
           
            $members = SectionAccess::where([
                ['section_id', $request->section_id],
                ['group_id', '==', null]
            ])->get()->pluck('user_id')->toArray();
            
            $groups = SectionAccess::where([
                ['section_id', $request->section_id],
                ['user_id', '==', 0]
            ])->get()->pluck('group_id')->toArray();
                
            $deletedMembers = SectionAccess::whereNotIn('user_id', $request->users ?? [])->where([
                ['group_id', '==', null],
                ['section_id', $request->section_id],
                ['user_id', '!=', Auth::id()]
            ])->get();
           
            $deletedGroups = SectionAccess::whereNotIn('group_id', $request->groups ?? [])->where([
                ['group_id', '!=', 1],
                ['section_id', $request->section_id],
                ['user_id', '!=', Auth::id()]
            ])->where('user_id', '==', 0)->get();
          
            foreach ($deletedMembers as $member) {
                $this->logCustomMessage(
                    'revoke_user_folder_access',
                    $member,
                    'Access to folder "' . $member['section']['name'] . '" was revoked for ' . $member['user']['name'] . ' by ' . Auth::user()->name,
                    $member,
                    'Revoke an access to a folder',
                    new Activity()
                );
            }

            foreach ($deletedGroups as $group) {
                $this->logCustomMessage(
                    'revoke_group_folder_access',
                    $group,
                    'Access to folder "' . $group['section']['name'] . '" was revoked for ' . $group['group']['name'] . ' by ' . Auth::user()->name,
                    $group,
                    'Revoke an access to a folder',
                    new Activity()
                );
            }

            SectionAccess::where([
                ['section_id', $request->section_id],
                ['user_id', '!=', Auth::id()]
            ])->delete();

            if (!$request->is_disabled) {
                foreach ($request->users as $user) {
                    $sectionAccess = SectionAccess::create([
                        'section_id' => $request->section_id,
                        'user_id' => $user,
                        'group_id' => 0,
                        'access_level' => 2,
                        'shared_by' => Auth::id(),
                        'shared_date' => now()
                    ]);
                    if (!in_array($user, $members) && $user != Auth::id()) {
                        $this->logCustomMessage(
                            'grant_user_folder_access',
                            $sectionAccess,
                            $sectionAccess['user']['name'] . ' was granted access to folder "' . $sectionAccess['section']['name'] . '" by ' . Auth::user()->name,
                            $sectionAccess,
                            'Grant an access to a folder',
                            new Activity()
                        );
                    }
                }

                foreach ($request->groups as $group) {
                    $sectionAccess = SectionAccess::create([
                        'section_id' => $request->section_id,
                        'user_id' => 0,
                        'group_id' => $group,
                        'access_level' => 2,
                        'shared_by' => Auth::id(),
                        'shared_date' => now()
                    ]);
                    if (!in_array($group, $groups)) {
                        $this->logCustomMessage(
                            'grant_group_folder_access',
                            $sectionAccess,
                            $sectionAccess->group->name . ' was granted access to folder "' . $sectionAccess->section->name . '" by ' . Auth::user()->name,
                            $sectionAccess,
                            'Grant an access to a folder',
                            new Activity()
                        );
                    }
                }
            }

            DB::connection(env('DMS_DB_CONNECTION'))->commit();
            return response()->json([
                'message' => 'Success'
            ], 200);
        } catch (Exception $e) {
            DB::connection(env('DMS_DB_CONNECTION'))->rollBack();
            return response()->json([
                'errors'    =>  ['There is a problem in assigning internal access.'],
                'msg'       =>  $e->getMessage()
            ], 500);
        }
    }

    public function fetchGroupBySectionId(Request $request)
    {
        return Role::whereHas('sectionAccess', function ($query) use ($request) {
            $query->where([
                ['section_id', $request->section_id],
            ]);
        })->has('roleHasSystem')->get();
    }

    public function fetchUserBySectionId(Request $request)
    {
        return User::whereHas('section_access', function ($query) use ($request) {
            $query->where([
                ['section_id', $request->section_id],
            ]);
        })->get();
    }

    public function fetch(Request $request)
    {
        return SectionAccess::where('group_id', $request->role_id)->get();
    }

    public function listSharedFolders(Request $request)
    {
        $paginate = $request->page_count ? intval($request->page_count) : env('DEFAULT_PAGECOUNT');
        $authUserRoles = Auth::user()->roles->pluck('id');
        return Section::where('created_by', '!=', Auth::id())->whereHas('access', function ($query) use ($authUserRoles) {
            $query->where('user_id', Auth::id())->orWhereIn('group_id', $authUserRoles);
        })->without(['access', 'files'])->with(['sharedBy.sharedBy'])->paginate($paginate);
    }
}
