<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Paste;
use Auth;
use App\User;
use App\Log;
use App\PasteRedirect;
use Redirect;
use \Input;
use \Hash;
use RoleId;
use Session;
use Cookie;
use DB;
use Carbon\Carbon;
use ViKon\Diff\Diff;

class AdminController extends Controller
{
	private function resizeImage($image, $imageHeight, $imageWidth, $newImageSize = 50){;
		$newImage = imagecreatetruecolor($newImageSize, $newImageSize);
		imagecopyresampled($newImage, $image, 0, 0, 0, 0, $newImageSize, $newImageSize, $imageWidth, $imageHeight);
		return $newImage;
	}

	private function formatBytes($bytes, $precision = 2) { 
		$units = array('B', 'KB', 'MB', 'GB', 'TB'); 

		$bytes = max($bytes, 0); 
		$pow = floor(($bytes ? log($bytes) : 0) / log(1024)); 
		$pow = min($pow, count($units) - 1); 

		// Uncomment one of the following alternatives
		// $bytes /= pow(1024, $pow);
		// $bytes /= (1 << (10 * $pow)); 

		return round($bytes, $precision) . ' ' . $units[$pow]; 
	} 
	private function jsonError($msg = null){
		$r = (is_null($msg) ? ['status' => 'err'] : ['status' => 'err', 'msg' => $msg]);
		return response()->json($r);
	}
	
	public function edituser($username, Request $request){
		$myUser = newGetUser();
		$user = User::where('username', $username)->first();

        // Accessing user must:
        //  - Be logged in
        //  - Possess a role higher than the profile user's role
        //  - Be a developer or higher
        $canEditUser = !is_null($myUser) && !is_null($user) && $user->role < $myUser->role && $myUser->isDeveloper(true);

		if ($request->isMethod('get')) {
			if ($myUser == null || !$myUser->isDeveloper(true) || is_null($user)) {
				return redirect('/');
			}

			$reset = DB::table('password_reset')
                ->where([
                    'user_id' => $user->id,
                    'used' => 0,
                    'expired' => 0,
                ])
                ->get();

			if ($reset->count() < 1) {
				$reset = null;
			}

			if ($user->sess_end <= floor(microtime(true) * 1000)) {
				DB::table('users')
                    ->where('username', $user->username)
                    ->update([
                        'session' => NULL,
                        'sess_end' => NULL,
                    ]);

				$user->session = NULL;
				$user->sess_end = NULL;
			}

			$roles = DB::table('roles')->get();
			$products = DB::table('products')->get();

			$orderHistory = DB::table('orders')
                ->where([
                    'user_id' => $user->id,
                    'status' => 'InvoiceSettled'
                ])
                ->latest('created_at')
                ->limit(10)
                ->get();

			$usernameHistory = DB::table('username_logs')
                ->where(['uid' => $user->id])
                ->latest('changed_at')
                ->get();

			$affectedByBreach = DB::table('affected_usernames')
                    ->where('username', $user->username)
                    ->count() > 0;

			$requiresPasswordReset = false;

			if ($user->last_seen > 1636416000000 && $user->last_seen < 1641330000000) {
				$requiresPasswordReset = true;
			} 
			return view('edituser', [
                'canEditUser' => $canEditUser,
                'user' => $user,
                'myUser' => $myUser,
                'reset' => $reset,
                'orderHistory' => $orderHistory,
                'usernameHistory' => $usernameHistory,
                'roles' => $roles,
                'products' => $products,
                'affectedInBreach' => $affectedByBreach,
                'requiresPasswordReset' => $requiresPasswordReset,
            ]);
		}

		if (!$request->isMethod('post')) {
			return $this->jsonError();
		}

		if (is_null($user)) {
			return response()->json(['status' => 'err', 'msg' => 'User does not exist.']);
		}
		if (!$myUser->isDeveloper(true)) {
			return response()->json(['status' => 'err', 'msg' => 'You do not have permission.']);
		}

        // Check for permission to edit the account.
		if (!$canEditUser) {
			return response()->json(['status' => 'err', 'msg' => 'You cannot edit that user.']);
		}

		$t = Input::get('type');
		if ($t == "auth-2fa") {
            if (!$myUser->isManager(true)) {
                return response()->json(['status' => 'err', 'msg' => 'Insufficient permission.']);
            }

			if(!$user->tfa_enabled && $user->role < RoleId::COUNCIL && $user->forced == 0){
				return response()->json(['status'=>'done']); // dont need to be authed if they dont have 2fa enabled
			}
			$v = Input::get('value');
			DB::table('users')->where('id', $user->id)->update(['tfa_auth' => !$v]);
			return response()->json(['status'=>'done']);

		} else if ($t == "force-2fa") {
            if (!$myUser->isManager(true)) {
                return response()->json(['status' => 'err', 'msg' => 'Insufficient permission.']);
            }

			if($user->role >= RoleId::COUNCIL){
				return response()->json(['status'=>'done']); // cant unforce staff
			}
			$v = Input::get('value');
			DB::table('users')->where('id', $user->id)->update(['tfa_forced' => !$v]);
			return response()->json(['status'=>'done', 'x' => $v]);

		} else if ($t == "disable-2fa") {
            if (!$myUser->isManager(true)) {
                return response()->json(['status' => 'err', 'msg' => 'Insufficient permission.']);
            }

			DB::table('users')->where('id', $user->id)->update(['tfa_enabled' => 0, 'tfa_secret' => null, 'tfa_auth' => 0]);
			return response()->json(['status'=>'done']);

		}else if($t == "username"){

			$value = Input::get('value');
			if(!empty($value)){
				if(preg_match("/[^a-zA-Z0-9_]+/", $value)){
					return response()->json(['status'=>'err','msg'=>'Username must be alphanumeric.']);
				}
				if(strlen($value) < 2){
					return response()->json(['status'=>'err','msg'=>'Username must be at least 2 characters long.']);
				}
				if(strlen($value) > 30){
					return response()->json(['status'=>'err','msg'=>'Username must be less than 31 characters.']);
				}
				if(DB::table('users')->where('username', $value)->count() > 0 || strtolower($value) == "anonymous"){
					return response()->json(['status'=>'err','msg'=>'Username is taken.']);
				}

				DB::transaction(function() use($value, $myUser, $user){
					DB::table('users')->where('id', $user->id)->update(['username' => $value]);
					DB::table('username_logs')->insert(['uid' => $user->id, 'username_before' => $user->username, 'username_after' => $value, 'changed_at' => Carbon::now()]);
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Changed username of <a href="/user/'. $value .'">' . $user->username . '</a> to ' . $value]);
					}
				});
				return response()->json(['status'=>'done']);
			}
		}else if($t == "bio"){
			if(strlen(Input::get('value')) > 200){
				return response()->json(['status' => 'err', 'msg' => 'Bio is too long. Max length is 200 characters.']);
			}
			if($myUser->role > RoleId::COUNCIL){
				Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Changed bio of ' . $user->username]);
			}
			DB::table('users')->where('id', $user->id)->update(['bio' => Input::get('value')]);
			return response()->json(['status' => 'done', 'msg' => 'Successfully updated bio.']);
		}else if($t == "email"){
			if(!empty(Input::get('value'))){
				if(Input::get('value') == $user->email){
					return response()->json(['status'=>'done', 'msg'=>'Done.']);
				}
				if (!filter_var(Input::get('value'), FILTER_VALIDATE_EMAIL) || strlen(Input::get('value')) > 254) {
					return response()->json(['status'=>'err','msg'=>'Invalid email.']);
				}
				if(DB::table('users')->where('email', Input::get('value'))->count() > 0){
					return response()->json(['status'=>'err','msg'=>'Email is already in use.']);
				}
				if($myUser->role > RoleId::COUNCIL){
					Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Changed email of ' . $user->username . ' to ' . Input::get('value')]);
				}
				DB::table('users')->where('id', $user->id)->update(['email' => Input::get('value')]);
				return response()->json(['status'=>'done', 'msg'=>'Email changed.']);
			}
		}else if($t == "image"){
			$valid = array("jpg", "jpeg", "png", "gif");
			$normalSize = 120; // 120 px

			if(!array_key_exists('image', $_FILES)){
				return response()->json(['status' => 'err', 'msg' => 'Image not set.']);
			}

			$file = $_FILES['image'];
			$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
			$name = substr(str_shuffle(str_repeat("0123456789abcdef", 5)), 0, 32);
			/**
			 * Reiko - Mar 14th 2024
			 * Static path was set. Used same variables from UserController.php
			 * Allows for staff to change PFP of a user
			 */
			$cdnRoot = env('CDN_STATIC_ROOT');

			$photokey = Input::get('modal');
			if ($photokey != "profile_pic" && $photokey != "banner_pic"){
				return $this->jsonError('Invalid Image type.');
			}

			$path = $cdnRoot . "/$photokey/"; // path to save to

			if(!in_array($ext, $valid)){
				return response()->json(['status' => 'err', 'msg' => 'Invalid format. Format must be either: jpg, jpeg, png, gif']); // Added gif as it is also valid as mentioned in the variable. Reiko, Mar 14th 2024
			}

            // Normalize jpeg to jpg.
            if ($ext === 'jpeg') {
                $ext = 'jpg';
            }

			$filelimit = 1024000;
			if($myUser->role >= 1){
				$filelimit = 3072000; // 3mb
			}
			if($file['size'] > $filelimit){
				return response()->json(['status' => 'err', 'msg' => 'Image too large. Limit ' . $this->formatBytes($filelimit)]);
			}
			if(!isset($file['tmp_name'])){
				return $this->jsonError('Image wasnt uploaded');
			}
			$properties = getimagesize($file['tmp_name']); // resize image vvvv
			if($properties === false){
				return response()->json(['status' => 'err', 'msg' => 'Error']);
			}

			switch ($properties[2]){ // enum image type
				case IMAGETYPE_PNG:
					$simage = imagecreatefrompng($file['tmp_name']);
					$image = imagecreatefrompng($file['tmp_name']);

					$smallImage = $this->resizeImage($simage, $properties[0], $properties[1]);
					$normalImage = $this->resizeImage($image, $properties[0], $properties[1], $normalSize);

					imagepng($smallImage, $path . $name . '_50x50.'.$ext);
					imagepng($normalImage, $path . $name.'.'.$ext);
					break;
				case IMAGETYPE_JPEG:
					$simage = imagecreatefromjpeg($file['tmp_name']);
					$image = imagecreatefromjpeg($file['tmp_name']);

					$smallImage = $this->resizeImage($simage, $properties[0], $properties[1]);
					$normalImage = $this->resizeImage($image, $properties[0], $properties[1], $normalSize);

					imagejpeg($smallImage, $path . $name . '_50x50.'.$ext);
					imagejpeg($normalImage, $path . $name.'.'.$ext);
					break;
				case IMAGETYPE_GIF:
					/**
					 * Fixed the use of GIFs in /edit for dev+ role
					 * Code gathered from 531-535 in UserController.php
					 */
					if(!move_uploaded_file($file["tmp_name"], $path . $name.'.'.$ext)){
						return $this->jsonError('Error: Image not uploaded.');
					}
					break;
				default:
					return response()->json(['status' => 'err', 'msg' => 'Invalid image type']);
			}

			if(file_exists($path.$name.'.'.$ext)){
				$user->profile_pic = $name.'.'.$ext;
				$user->has_small_profile_pic = 1;
				$user->save();
			}else{
				return response()->json(['status' => 'err', 'msg' => 'Error: Image not uploaded']);
			}

			if($myUser->role > RoleId::COUNCIL){
				// Changed this to show link to profile -- Mar 14th, Reiko
				Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Changed profile picture of  <a href="/user/' . $user->username . '">' . $user->username . '</a>']);
			}
			return response()->json(['status' => 'done', 'msg' => 'done']);

		}else if($t == "remove-image"){
			if($user->profile_pic == NULL){
				return response()->json(['status' => 'done', 'msg' => 'Successfully removed profile picture.']);
			}
			if(strlen($user->profile_pic) < 32){
				return response()->json(['status' => 'err', 'msg' => 'Error... profile pic is broke?']);
			}
			$image_path = '/var/www/cdn/'.$user->profile_pic;
			$smallimage_path = '/var/www/cdn/'.explode('.', $user->profile_pic)[0].'_50x50.'.explode('.', $user->profile_pic)[1];
			try{
				if(file_exists($image_path)){
					unlink($image_path);
					if($myUser->has_small_profile_pic){
						unlink($smallimage_path);
					}
				}
			}catch (ErrorException $e){
			}finally{
				DB::transaction(function() use ($myUser, $user){
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Removed profile picture of ' . $user->username]);
					}
					$user->profile_pic = null;
					$user->has_small_profile_pic = 0;
					$user->save();
				});
			}
			return response()->json(['status' => 'done', 'msg' => 'Successfully removed profile picture.']);

		}else if($t == "password"){
			$reset = DB::table('password_reset')->where(['user_id' => $user->id, 'used' => 0, 'expired' => 0])->get();
			if(Input::get('action') == "cancel"){

				if($reset->count() < 1){
					return response()->json(['status' => 'err', 'msg' => 'User has no existing password reset links.']);
				}
				$reset = $reset[0];
				DB::table('password_reset')->where('user_id', $user->id)->update(['expired' => 1]);

				if($myUser->role > RoleId::COUNCIL){
					Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Deleted password reset link for <a href="/user/' . $user->username . '">' . $user->username . '</a>']);
				}

				return response()->json(['status' => 'done', 'msg' => 'Successfully deleted password reset link.']);

			}else if(Input::get('action') == "generate"){
				if($reset->count() > 0){
					return response()->json(['status' => 'err', 'msg' => 'User already has a password reset link.']);
				}

				$link = substr(str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 2)), 10, 50);

				DB::transaction(function() use ($user, $link, $myUser){
					DB::table('password_reset')->insert(['user_id' => $user->id, 'link' => $link, 'date' => time(), 'expires' => (time() + 604800)]);

					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Created password reset link for <a href="/user/' . $user->username . '">' . $user->username . '</a>']);
					}
				});

				return response()->json(['status' => 'done', 'msg' => 'Successfully generated link.', 'link' => $link]);
			}
		}else if($t == "delete"){
			if(!$myUser->isManager(true)){
				return response()->json(['status' => 'Failed', 'msg' => 'You have no permission, contact Operator.']);
			}else{
				DB::table('users_deleted')->insert([
					'id' => $user->id,
					'username' => $user->username,
					'email' => $user->email,
					'password' => $user->password,
					'session' => $user->session,
					'sess_end' => $user->sess_end,
					'joindate' => $user->joindate,
					'comments' => $user->comments,
					'pastes' => $user->pastes,
					'role' => $user->role,
					'admin' => $user->admin,
					'profile_pic' => $user->profile_pic,
					'bio' => $user->bio,
					'deletedby' => $myUser->id,
					'deleteddate' => floor(microtime(true) * 1000)
					]);

				DB::transaction(function() use ($user, $myUser){
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Deleted user ' . $user->username]);
					}
					DB::table('users')->where('id', $user->id)->delete();
				});
				return response()->json(['status' => 'done', 'msg' => 'done']);
			}
		} else if($t == "deletesession"){
			if (!$myUser->isDeveloper(true)) { // Not to worry, I have tested this on Mod, Manager & Admin. All work. Council will not work, obviously
				return response()->json(['status' => 'Failed', 'msg' => 'You have no permission, contact Operator.']);
			} else {
				// Creates a log for deleted sessions
				if($myUser->role > RoleId::COUNCIL){
					Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Deleted Session for <a href="/user/' . $user->username . '">' . $user->username . '</a>']);
				}
				DB::table('users')
					->where('username', $user->username)
					->update([
						'session' => null,
						'sess_end' => null,
						'tfa_session' => null, // Added this from the database as we want to delete all sessions, including 2FA session (if any exists)
					]);
				return response()->json(['status' => 'done', 'msg' => 'done']);
			}
		} else if($t == "lockaccount") { 
			if(!$myUser->isManager(true)){
				return response()->json(['status' => 'Failed', 'msg' => 'Nice try, nigga.']);
			} else {
				// Creates a log for locked accounts
				if($myUser->role > RoleId::COUNCIL){
					Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Locked account for <a href="/user/' . $user->username . '">' . $user->username . '</a>']);
				}
				DB::table('users')
					->where('username', $user->username)
					->update([
						'locked' => 1,
						'tfa_locked' => 1,
					]);
				return response()->json(['status' => 'done', 'msg' => 'done']);
			}
		} else if($t == "unlockaccount") { 
			if(!$myUser->isManager(true)){
				return response()->json(['status' => 'Failed', 'msg' => 'Nice try, nigga.']);
			} else {
				// Creates a log for locked accounts
				if($myUser->role > RoleId::COUNCIL){
					Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Unlocked account for <a href="/user/' . $user->username . '">' . $user->username . '</a>']);
				}
				DB::table('users')
					->where('username', $user->username)
					->update([
						'locked' => 0,
						'tfa_locked' => 0,
					]);
				return response()->json(['status' => 'done', 'msg' => 'done']);
			}

		} else if($t == 'role') {
			$role = Input::get('role');

			$rl = DB::table('roles')->where('id', $role)->get();

			if (
                $role != RoleId::COUNCIL &&
                $role != RoleId::DEVELOPER &&
                $role != RoleId::MOD &&
                $role != RoleId::MANAGER &&
                ($role > 0 && $rl->count() < 1)
            ) {
				return response()->json(['status' => 'err', 'msg' => 'Role does not exist.']);
			}

            if ($role >= $myUser->role) {
                return response()->json(['status' => 'err', 'msg' => 'You cannot promote users to an equal or higher rank than your own.']);
            }

			$to = '';

			if($role != $user->role){
				$council = $role == RoleId::COUNCIL;
                $isDeveloper = $role == RoleId::DEVELOPER;
				$mod = $role == RoleId::MOD;
                $isManager = $role == RoleId::MANAGER;

				if ($role == 0) {
					$to = 'Member';
				} else if ($role == RoleId::COUNCIL) {
                    $to = 'Council';
                } else if ($role == RoleId::DEVELOPER) {
                    $to = 'Developer';
				} else if ($role == RoleId::MOD) {
                    $to = 'Mod';
                } else if ($role == RoleId::MANAGER) {
                    $to = 'Manager';
				} else {
					$to = $rl[0]->name;
				}

				if (!$myUser->isManager(true)){
					return response()->json(['status' => 'err', 'msg' => 'Nice try idiot.']); // fuck
				} else {
				    DB::table('users')
                        ->where('id', $user->id)
                        ->update([
                            'council' => $council,
                            'is_developer' => $isDeveloper,
                            'mod' => $mod,
                            'is_manager' => $isManager,
                            'role' => $role,
                        ]);

					if ($myUser->role > RoleId::COUNCIL) {
						Log::create([
                            'uid' => $myUser->id,
                            'username' => $myUser->username,
                            'log' => 'Gave ' . $to . ' to <a href="/user/' . $user->username . '">' . $user->username . '</a>',
                        ]);
					}
				}
			}

			return response()->json(['status' => 'done']);
		}else if($t == 'upgrade'){
			$product = Input::get('product');
			$notify = Input::get('notify');

			$products = DB::table('products')->where('id', $product)->first();

			if(is_null($products)){
				return response()->json(['status' => 'err', 'msg' => 'Upgrade doesn\'t exist.']);
			}

			$to = $products->title;

			$removed = $user->applyUpgrade($product, $notify) == 'removed'; // did something get removed?

			if($myUser->role > RoleId::COUNCIL){
				Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => ($removed ? 'Removed' : 'Added') . ' upgrade ' . $to . ($removed ? ' from ' : ' to ') . '<a href="/user/' . $user->username . '">' . $user->username . '</a>']);
			}
			return response()->json(['status' => 'done']);
		}
		
	}

	public function users(Request $request) {
		$myUser = newGetUser();

		if (is_null($myUser) || !$myUser->isAdmin(true)) {
			return redirect('/');
		}

		// vars
		$id = $username = $email = $comments = $pastes = $role = $tfa_enabled = $username_wc = $email_wc = null;
		
		$limit = 50; // default amount of results to show
		$users = null;
		$search = $request->input('search');
		//
		if ($search) {
			$id = $request->input('userid', null);
			$username = $request->input('username', null);
			$email = $request->input('email', null);
			// $comments = $request->input('comments', null);
			// $pastes = $request->input('pastes', null);
			$role = $request->input('role', null);
			$tfa_enabled = $request->input('tfa', null);
			$limit = $request->input('limit', 50);
			$username_wc = $request->input('username-wc', false);
			$email_wc = $request->input('email-wc', false);
			
			$scharr = array();
			if(!is_null($id)){
				$scharr['id'] = $id;
			}
			if(!is_null($username) && !$username_wc){
				$scharr['username'] = $username;
			}
			if(!is_null($email) && !$email_wc){
				$scharr['email'] = $email;
			}
			if(!is_null($role)){
				$scharr['role'] = $role;
			}
			if(!is_null($tfa_enabled)){
				$scharr['tfa_enabled'] = $tfa_enabled;
			}
			
			$r = \App\User::where($scharr);
			if($username_wc){
				$r = $r->where('username', 'like', '%'.$username.'%');
			}
			if($email_wc){
				$r = $r->where('email', 'like', '%'.$email.'%');
			}
			$users = $r->latest('joindate')->limit($limit)->get();
		} else {
			$users = \App\User::latest('joindate')->limit($limit)->get();
		}
		$roles = DB::table('roles')->get();
		$flagsCount = DB::table('flags')->where('status', 0)->count();
		$editsCount = DB::table('edit_review')->where('handled', 0)->count();
		$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
		return view('admin.users', [
            'myUser' => $myUser,
            'users' => $users,
            'userCount' => $users->count(),
            'roles' => $roles,
            'flagsCount' => $flagsCount,
            'editsCount' => $editsCount,
            'blacklistCount' => $blacklistCount,
            'formData' => [
                'userid' => $id,
                'username' => $username,
                'email' => $email,
                'username-wc' => $username_wc == "on",
                'email-wc' => $email_wc == "on",
                'role' => $role,
                'tfa' => $tfa_enabled,
                'limit' => $limit,
			],
        ]);
		
	}

	public function stafflogs(Request $request) {
		$myUser = newGetUser();
	
		if (is_null($myUser) || !$myUser->isManager(true)) {
			return redirect('/');
		}
	
		// vars
		$user_id = $limit = null;
		$limit = 100; // default amount of results to show
		$logs = null;
		$search = $request->input('search');
		//
	
		if ($search) {
			$user_id = $request->input('userid', null);
			$limit = $request->input('limit', $limit);
	
			$scharr = array();
			if (!is_null($user_id)) {
				$scharr['uid'] = $user_id;
			}
	
			// nuh uh no
            // TODO: Create column on Log that restricts visibilities to certain roles.
			$logs = Log::where($scharr)
				->where('log', 'not like', '%hid paste%')
				->latest('created_at')
				->limit($limit)
				->get();
		} else {
			// nuh uh no
			$logs = Log::latest('created_at')
				->where('log', 'not like', '%hid paste%')
				->where('created_at', '>', Carbon::now()->subDays(2)->toDateTimeString())
				->limit($limit)
				->get();
		}
	
		$flagsCount = DB::table('flags')->where('status', 0)->count();
		$editsCount = DB::table('edit_review')->where('handled', 0)->count();
		$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
	
		return view('admin.stafflogs', [
			'myUser' => $myUser,
			'logs' => $logs,
			'logCount' => $logs->count(),
			'flagsCount' => $flagsCount,
			'editsCount' => $editsCount,
			'blacklistCount' => $blacklistCount,
			'formData' => [
				'userid' => $user_id,
				'limit' => $limit,
			],
		]);
	}
	

	public function hiddenlogs(Request $request) {
		$myUser = newGetUser();
	
		if (is_null($myUser) || !$myUser->isManager(true)) {
			return redirect('/');
		}
	
		// vars
		$user_id = $limit = null;
		$limit = 100; // default amount of results to show
		$logs = null;
		$search = $request->input('search');
		//
	
		if ($search) {
			$user_id = $request->input('userid', null);
			$limit = $request->input('limit', $limit);
	
			$scharr = array();
			if (!is_null($user_id)) {
				$scharr['uid'] = $user_id;
			}
	
			// mfw i gotta do this fucking nigger shit hahahaha
			$logs = Log::where($scharr)
				->where('log', 'like', '%hid paste%')
				->latest('created_at')
				->limit($limit)
				->get();
		} else {
			// how to rape manager+ performance 101
			$logs = Log::where('log', 'like', '%hid paste%')
				->latest('created_at')
				->where('created_at', '>', Carbon::now()->subDays(2)->toDateTimeString())
				->limit($limit)
				->get();
		}

		$logs->transform(function ($log) {
			preg_match('/\/upload\/([^\"]+)/', $log->log, $matches);
			if (!empty($matches[1])) {
				$pasteLink = $matches[1];
				$paste = DB::table('pastes')->where('link', $pasteLink)->first();
				if ($paste) {
					if ($paste->hidden_reason !== null) {
						$log->hidden_reason = $paste->hidden_reason;
					} else {
						$log->hidden_reason = 'No reason found';
					}
				} else {
					$log->hidden_reason = 'No reason found';
				}
			} else {
				$log->hidden_reason = 'No paste link found';
			}
			return $log;
		});


		return view('admin.hiddenlogs', [
			'myUser' => $myUser,
			'logs' => $logs,
			'logCount' => $logs->count(),
			'formData' => [
				'userid' => $user_id,
				'limit' => $limit,
			],
		]);
	}
	
	public function spamsystem(Request $request) {
		$myUser = newGetUser();
	
		if (is_null($myUser) || !($myUser->isManager(true) || $myUser->isDeveloper())) {
			return redirect('/');
		}

		return view('admin.spamsystem', ['myUser' => $myUser],
		);
	}

	public function main_admin(Request $request){
		$myUser = newGetUser();
		if(is_null($myUser) || !$myUser->isCouncil(true)){
			return $this->jsonError();
		}
		
		if ($myUser->isManager(true)) {
			$announcements = DB::table('site_announcements')->get();
			$roles = DB::table('roles')->orderBy('weight', 'desc')->get();
			$flagsCount = DB::table('flags')->where('status', 0)->count();
			$editsCount = DB::table('edit_review')->where('handled', 0)->count();
			$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
			return view('admin.manage_site', [
                'myUser' => $myUser,
				'announcement1' => $announcements[0],
				'announcement2' => $announcements[1],
				'announcement3' => $announcements[2],
				'announcement4' => $announcements[3],
				'roles' => $roles,
				'flagsCount' => $flagsCount,
				'editsCount' => $editsCount,
				'blacklistCount' => $blacklistCount,
            ]);
			/** 
			 * I have been given permission by Operator to allow the Developer role to have access to the maintenance mode button
			 * $myUser->isDeveloper() instead of $myUser->isDeveloper(true) has been chosen as this would only allow the Developer
			 * rank to see the following (as intended)
			 * 
			 * It would probably be a good idea to shift Developer as a higher rank to Moderator but that's uneeded at this current
			 * point in time.
			*/
		}  else if ($myUser->isDeveloper()) {
			$roles = DB::table('roles')->orderBy('weight', 'desc')->get();
			$flagsCount = DB::table('flags')->where('status', 0)->count();
			$editsCount = DB::table('edit_review')->where('handled', 0)->count();
			return view('admin.manage_site', [
                'myUser' => $myUser,
				'roles' => $roles,
				'flagsCount' => $flagsCount,
				'editsCount' => $editsCount,
            ]);
		} else if ($myUser->isMod(true)) {
			$edits = DB::table('edit_review')
                ->latest('date')
                ->where('handled', 0)
                ->leftJoin('users', 'users.id', '=', 'edit_review.user_id')
                ->leftJoin('pastes', 'pastes.id', '=', 'edit_review.doxId')
                ->get(['edit_review.*', 'pastes.created_at', ...MINIMUM_USER_COLUMNS_FOR_DISPLAY]);
			$flagsCount = DB::table('flags')->where('status', 0)->count();
			$editsCount = $edits->count();
			return view('admin.edits', [
                'myUser' => $myUser,
				'edits' => $edits,
				'flagsCount' => $flagsCount,
				'editsCount' => $editsCount,
            ]);
		} else {
			$flag = DB::table('flags')->where('uid', $myUser->id)->where('status', '!=', '3')->orderBy('date', 'desc');
			$flags = $flag->get();
			
			$myflagcount = $flag->count();
			
			return view('admin.flags', [
				'myUser' => $myUser,
				'myflagcount' => $flags,
				'myacceptedflagcount' => $flags->where('status', 1),
				'mydeniedflagcount' => $flags->where('status', 2),
				'myflagcountthisweek' => $flags->where('date', '>', floor(microtime(true) * 1000) - (7 * 24 * 60 * 60 * 1000))->count(),
				'flags' => $flag->limit(100)->get(),
			]);
		}
		

	}

	
	public function flags(Request $request){
		$myUser = newGetUser();
		if(is_null($myUser) || !$myUser->isCouncil(true)){
			return $this->jsonError();
		}
		$rtn = [];
		if($myUser->isManager(true)){
			$flags = DB::table('flags')->where('status', 0)->orderBy('date', 'desc')->get();
			$council = User::where('role', RoleId::COUNCIL)->get();
			$flagsCount = DB::table('flags')->where('status', 0)->count();
			$editsCount = DB::table('edit_review')->where('handled', 0)->count();
			$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
			$flagWords = DB::table('flag_words')->get();


			
			
			$councilFlags = [];
			foreach($council as $councilUser){
				// $councilFlag[$councilUser->username] = [];
				$userFlags = DB::table('flags')->where('uid', $councilUser->id)->get();
				$totalDenies = $userFlags->where('status', 2)->count();
				$totalFlags = $userFlags->where('status', '!=', 3)->count();
				$pastWeek = $userFlags->where('status', '!=', 3)->where('date', '>', floor(microtime(true) * 1000) - (7 * 24 * 60 * 60 * 1000))->count();
				$councilFlags[$councilUser->username] = ['totalDenies' => $totalDenies, 'totalFlags' => $totalFlags, 'pastWeek' => $pastWeek, 'nameStyle' => $councilUser->getNameStyle(), 'userID' => $councilUser->id];
			}
			$rtn = [
				'myUser' => $myUser,
				'flags' => $flags,
				'councils' => $council,
				'councilFlags' => $councilFlags,
				'flagsCount' => $flagsCount,
				'editsCount' => $editsCount,
				'blacklistCount' => $blacklistCount,
				'flagWords' => $flagWords
			];
		} else if($myUser->isDeveloper(true)) {
			$flags = DB::table('flags')->where('status', 0)->orderBy('date', 'desc')->get();
			$flagsCount = DB::table('flags')->where('status', 0)->count();
			$editsCount = DB::table('edit_review')->where('handled', 0)->count();

			$council = User::where('role', RoleId::COUNCIL)->get();
			$councilFlags = [];
			foreach($council as $councilUser){
				// $councilFlag[$councilUser->username] = [];
				$userFlags = DB::table('flags')->where('uid', $councilUser->id)->get();
				$totalDenies = $userFlags->where('status', 2)->count();
				$totalFlags = $userFlags->where('status', '!=', 3)->count();
				$pastWeek = $userFlags->where('status', '!=', 3)->where('date', '>', floor(microtime(true) * 1000) - (7 * 24 * 60 * 60 * 1000))->count();
				$councilFlags[$councilUser->username] = ['totalDenies' => $totalDenies, 'totalFlags' => $totalFlags, 'pastWeek' => $pastWeek, 'nameStyle' => $councilUser->getNameStyle(), 'userID' => $councilUser->id];
			}

			
			$rtn = [
				'myUser' => $myUser,
				'flags' => $flags, 
				'councils' => $council,
				'councilFlags' => $councilFlags,
				'flagsCount' => $flagsCount,
				'editsCount' => $editsCount
			];
		}else{
			$flag = DB::table('flags')->where('uid', $myUser->id)->where('status', '!=', '3')->orderBy('date', 'desc');
			$myflagcount = $flag->count();
			
			$rtn = [
				'myUser' => $myUser,
				'flags' => $flag->limit(100)->get(),
				'myflagcountthisweek' => $flag->where('date', '>', floor(microtime(true) * 1000) - (7 * 24 * 60 * 60 * 1000))->count(),
				'myflagcount' => $myflagcount,
				'myacceptedflagcount' => $flag->where('status', 1)->count(),
				'mydeniedflagcount' => $flag->where('status', 2)->count(),
			];
		}
		return view('admin.flags', $rtn);

	}

	public function flaglogs(Request $request){
		$myUser = newGetUser();
		if(is_null($myUser) || !$myUser->isDeveloper(true)){
			return $this->jsonError();
		}
		// vars
		$handled_by = $user_id = $paste_id = $status = $limit = null;
		$limit = 100; // default amount of results to show
		$flags = null;
		$search = $request->input('search');
		//
		$statuses = ['Pending', 'Accepted', 'Denied', 'Canceled'];
		if ($search) {
			$handled_by = $request->input('handledby', null);
			$user_id = $request->input('userid', null);
			$paste_id = $request->input('pasteid', null);
			$status = $request->input('status', null);
			$limit = $request->input('limit', $limit);

			if (($myUser->isMod() || $myUser->isDeveloper()) && $limit > 1000) {
				$limit = 1000; // dev+ 1k max
			}

			$scharr = array();
			if(!is_null($handled_by)){
				$scharr['handled_by'] = $handled_by;
			}
			if(!is_null($user_id)){
				$scharr['uid'] = $user_id;
			}
			if(!is_null($paste_id)){
				$scharr['pid'] = $paste_id;
			}
			if(!is_null($status)){
				$scharr['status'] = $status;
			}
			
			$flags = DB::table('flags')->where($scharr)->latest('date')->limit($limit)->get();
		}else{
			$flags = DB::table('flags')->latest('date')->limit($limit)->get();
		}
		
		$flagsCount = DB::table('flags')->where('status', 0)->count();
		$editsCount = DB::table('edit_review')->where('handled', 0)->count();
		$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();

		return view('admin.flaglogs', ['myUser' => $myUser, 'flags' => $flags, 'statuses' => $statuses, 'flagCount' => $flags->count(), 'flagsCount' => $flagsCount, 'editsCount' => $editsCount, 'blacklistCount' => $blacklistCount, 'formData' => [
			'handledby' => $handled_by,
			'pasteid' => $paste_id,
			'userid' => $user_id,
			'status' => $status,
			'limit' => $limit
			]
			]);

	}
	public function usernamelogs(Request $request){
		$myUser = newGetUser();

		if (is_null($myUser) || !$myUser->isManager(true)) {
			return $this->jsonError();
		}

		// vars
		$user_id = $username_old = $username_new = null;
		$limit = 50; // default amount of results to show
		$results = null;
		$search = $request->input('search');
		//

		if ($search) {
			$user_id = $request->input('userid', null);
			$username_old = $request->input('username_old', null);
			$username_new = $request->input('username_new', null);
			$limit = $request->input('limit', 50);
			
			$scharr = array();
			if(!is_null($user_id)){
				$scharr['uid'] = $user_id;
			}
			if(!is_null($username_old)){
				$scharr['username_before'] = $username_old;
			}
			if(!is_null($username_new)){
				$scharr['username_after'] = $username_new;
			}
			
			$results = DB::table('username_logs')->where($scharr)->latest('changed_at')->limit($limit)->get();
		}else{
			$results = DB::table('username_logs')->latest('changed_at')->limit($limit)->get();
		}
		$flagsCount = DB::table('flags')->where('status', 0)->count();
		$editsCount = DB::table('edit_review')->where('handled', 0)->count();
		$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
		return view('admin.logs_username_logs', [
            'myUser' => $myUser,
            'results' => $results,
            'resultCount' => $results->count(),
            'flagsCount' => $flagsCount,
            'editsCount' => $editsCount,
            'blacklistCount' => $blacklistCount,
            'formData' => [
                'userid' => $user_id,
                'username_old' => $username_old,
                'username_new' => $username_new,
                'limit' => $limit,
			],
        ]);
	}

	public function orderlogs(Request $request){
		$myUser = newGetUser();
		if(is_null($myUser) || !$myUser->isManager(true)){
			return $this->jsonError();
		}
		// vars
		$order_id = $user_id = $status = $product_id = null;
		$limit = 50; // default amount of results to show
		$orders = null;
		$search = $request->input('search');
		$statuses = ['InvoiceCreated', 'InvoiceSettled', 'InvoiceReceivedPayment', 'InvoiceExpired'];
		//

		if($search){
			$order_id = $request->input('orderid', null);
			$user_id = $request->input('userid', null);
			$status = $request->input('status', null);
			$product_id = $request->input('productid', null);
			$limit = $request->input('limit', 50);
			
			$scharr = array();
			if(!is_null($order_id)){
				$scharr['order_id'] = $order_id;
			}
			if(!is_null($user_id)){
				$scharr['user_id'] = $user_id;
			}
			if(!is_null($status)){
				$scharr['status'] = $status;
			}
			if(!is_null($product_id)){
				$scharr['product_id'] = $product_id;
			}
			
			$orders = \App\Order::where($scharr)->latest('updated_at')->limit($limit)->get();
		}else{
			$orders = \App\Order::latest('updated_at')->limit($limit)->get();
		}
		$products = DB::table('products')->get();
		$flagsCount = DB::table('flags')->where('status', 0)->count();
		$editsCount = DB::table('edit_review')->where('handled', 0)->count();
		$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
		return view('admin.orders', ['myUser' => $myUser, 'orders' => $orders, 'orderCount' => $orders->count(), 'products' => $products, 'statuses' => $statuses, 'flagsCount' => $flagsCount, 'editsCount' => $editsCount, 'blacklistCount' => $blacklistCount, 'formData' => [
			'orderid' => $order_id,
			// 'invoiceid' => $invoice_id,
			'userid' => $user_id,
			'status' => $status,
			'productid' => $product_id,
			'limit' => $limit
			]
			]);
	}

	public function blacklist(){
		$myUser = newGetUser();

		if (is_null($myUser) || !$myUser->isAdmin(true)) {
			return $this->jsonError();
		}
		
		$newblacklist = DB::table('blacklist')->latest('id')->get();
		$blacklist = DB::table('word_blacklist')->latest('date')->get();
		$blacklist_pastes = Paste::where(['blacklist' => 1, 'hidden' => 0])->get();
		$flagsCount = DB::table('flags')->where('status', 0)->count();
		$editsCount = DB::table('edit_review')->where('handled', 0)->count();
		return view('admin.blacklist', [
			'myUser' => $myUser,
			'words' => $blacklist,
			'blacklist' => $newblacklist,
			'flagsCount' => $flagsCount,
			'editsCount' => $editsCount,
			'blacklistCount' => $blacklist_pastes->count(),
			'blacklisted_pastes' => $blacklist_pastes
        ]);
	}

	public function edits(Request $request){
		$myUser = newGetUser();
		if(is_null($myUser) || !$myUser->isDeveloper(true)){
			return $this->jsonError();
		}
		$edits = DB::table('edit_review')
            ->latest('date')
            ->where('handled', 0)
            ->leftJoin('users', 'users.id', '=', 'edit_review.user_id')
            ->join('pastes', 'doxId', '=', 'pastes.id')
            ->get(['edit_review.*', 'pastes.created_at', ...MINIMUM_USER_COLUMNS_FOR_DISPLAY]);

		$flagsCount = DB::table('flags')->where('status', 0)->count();
		if($myUser->isAdmin(true)){
			$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
		}
	
		return view('admin.edits', ['myUser' => $myUser, 'edits' => $edits, 'blacklistCount' => isset($blacklistCount) ? $blacklistCount : null, 'flagsCount' => $flagsCount, 'editsCount' => $edits->count()]);

	}

	public function editshow($link = null){
		$myUser = newGetUser();
		if($myUser == null){
			return redirect('/');
		}
		if (!$myUser->isDeveloper(true)) {
			return redirect('/');
		}
		if($link != null){
			$original = DB::table('pastes')->where('link', $link)->first();
			$new = DB::table('edit_review')->where(['link' => $link, 'handled' => 0])->first();
			if(!$original){
				return redirect('/');
			}
			if(!$new){
				return redirect('/');
			}
			$created_by = User::find($original->created_by);
			$showdiff = true;
			if(strlen($new->newpost) > 60000){
				$showdiff = false;
				$diff = htmlentities($original->content);
			}else{
				$diff = Diff::compare($original->content, $new->newpost)->toHTML();
			}
			$new->newpost = htmlentities($new->newpost);
			$original->content = htmlentities($original->content);

			return view('admin_edits_show', ['myUser' => $myUser, 'original' => $original, 'new' => $new, 'created_by' => $created_by, 'diff' => $diff, 'showdiff' => $showdiff]);
		}
    }
	
	public function showflag($link = null){
		$myUser = newGetUser();
		if($myUser == null){
			return redirect('/');
		}
		if(!$myUser->isDeveloper(true)){
			return redirect('/');
		}
		if($link != null){

		}

		$paste = DB::table('pastes')->where('link', $link)->get();
		if($paste->count() < 1){
			return redirect('/');
		}
		$paste = $paste->first();

		$flag = DB::table('flags')->where(['pid' => $paste->id, 'status' => 0])->get();

		if($flag->count() < 1){
			return redirect('/');
		}

		$staffnotes = null;
		if($myUser != null && $myUser->isDeveloper(true)){
			$staffnotes = DB::table('staffnotes')->where('pid', $paste->id)->get();
		}

		$flag = $flag->first();

		$created_by = User::find($paste->created_by);
		$flagged_by = 0;
		if($flag->uid != 0){
			$flagged_by = User::find($flag->uid);
		}
	
		return view('showflag', ['myUser' => $myUser, 'paste' => $paste, 'flag' => $flag, 'staff_notes' => $staffnotes, 'created_by' => $created_by, 'flagged_by' => $flagged_by]);
		
	}
	
	public function errorlogs(){
		$myUser = newGetUser();
		if($myUser == null){
			return redirect('/');
		}
		if(!$myUser->isManager(true)){
			return redirect('/');
		}
		
		$edits = DB::table('edit_review')->latest('date')->where('handled', 0)->get();

		$flagsCount = DB::table('flags')->where('status', 0)->count();
		if($myUser->isAdmin()){
			$blacklistCount = DB::table('pastes')->where(['hidden' => 0, 'blacklist' => 1])->count();
		}
		
		$logs = null;
		try{
			$lines = file(env('SYSTEM_LOG_LOCATION'));
			$logs = implode(array_slice($lines, env('ERROR_LOGS_MAX_LINES')));
		}catch(\ErrorException $e){
			$logs = $e;
		}
		return view('admin.errorlogs', ['myUser' => $myUser, 'logs' => $logs]);
		
	}
	
	public function test(){
		return view('test');
	}

	public function action(Request $request) {
		if (!$request->isMethod('post')){
			return abort(404);
		}

		$myUser = newGetUser();
		if($myUser == null){
			return response()->json(['status' => 'err', 'msg' => 'Not logged in.']);
		}

		if(!$myUser->isDeveloper(true)){
			return response()->json(['status' => 'err']);
		}


			
		$id = Input::get('dox_id');
			
		if (!is_numeric($id)) {
			return response()->json(['status' => 'err']);
		}

		$paste = DB::table('pastes')->where('id', $id)->get();

		if($paste->count() < 1){
			return response()->json(['status' => 'err']);
		}
		$paste = $paste[0];
		if(Input::get('unblacklist_dox')){
			if($myUser->isAdmin()){
				if($paste->blacklist == 1){
					DB::table('pastes')->where('id', $id)->update(['blacklist' => 0]);
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Unblacklisted paste: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
					}
					return response()->json(['status' => 'done', 'msg' => 'done']);
				}
			}else{
				return response()->json(['status' => 'err']);
			}
		}else if(Input::get('toggle_cmts')){
			if ($myUser->isManager(true)) {
				if ($paste->disable_cmts == 1) {
					DB::table('pastes')->where('id', $id)->update(['disable_cmts' => 0]);
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Enabled comments on paste: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
					}
					return response()->json(['status' => 'done', 'msg' => 'done', 'enabled' => 0]);
				} else {
					DB::table('pastes')->where('id', $id)->update(['disable_cmts' => 1]);
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Disabled comments on paste: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
					}
					return response()->json(['status' => 'done', 'msg' => 'done', 'enabled' => 1]);
				}
			}else{
				return response()->json(['status' => 'err']);
			}
		} else if(Input::get('edit_toggle')){
			if ($myUser->isDeveloper(true)) {
				if ($paste->editbanned == 1) {
					DB::table('pastes')->where('id', $id)->update(['editbanned' => 0]);
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Disabled edit ban for: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
					}
					return response()->json(['status' => 'done', 'msg' => 'done', 'enabled' => 0]);
				} else {
					DB::table('pastes')->where('id', $id)->update(['editbanned' => 1]);
					if($myUser->role > RoleId::COUNCIL){
						Log::create(['uid' => $myUser->id, 'username' => $myUser->username, 'log' => 'Enabled edit ban for: <a href="/upload/' . $paste->link . '">' . htmlspecialchars($paste->title) . '</a>']);
					}
					return response()->json(['status' => 'done', 'msg' => 'done', 'enabled' => 1]);
				}
			}else{
				return response()->json(['status' => 'err']);
			}
		}
	}
}
