<?php

if(!defined('SOFTACULOUS')){
	die('Hacking Attempt');
}

class AIPermissionManager {
	private $file_manager;
	private $project_path;
	private $user_home_dir;

	public function __construct(AIFileManager $file_manager, $project_path, $user_home_dir){
		$this->file_manager = $file_manager;
		$this->project_path = rtrim($project_path, '/');
		$this->user_home_dir = $user_home_dir ? rtrim($user_home_dir, '/') : $this->project_path;
	}

	public function build_permission_request($tool_name, array $params){
		if($tool_name === 'php_eval'){
			return array(
				'type' => 'tool',
				'tool_name' => 'php_eval',
				'key' => 'php_eval:*',
				'summary' => 'Run arbitrary PHP code',
				'detail' => isset($params['code']) ? $params['code'] : '',
				'detail_label' => 'PHP code'
			);
		}

		$power_tools = array('wp_manage_post', 'wp_manage_page', 'wp_manage_plugin', 'wp_manage_theme', 'wp_manage_user', 'wp_update_setting', 'wp_core_action');
		if(in_array($tool_name, $power_tools)){
			return array(
				'type' => 'power',
				'tool_name' => $tool_name,
				'key' => 'power:' . $tool_name,
				'summary' => 'High-impact WordPress action: ' . $tool_name,
				'detail' => json_encode($params),
				'detail_label' => 'Action details',
				'allow_always' => false
			);
		}

		$path_keys = array('path', 'source', 'destination');
		$paths = array();
		foreach($path_keys as $k){
			if(!empty($params[$k])){
				$resolved = $this->resolve_param_path($params[$k]);
				if($resolved !== null){
					$paths[$k] = $resolved;
				}
			}
		}

		if(empty($paths)){
			return null;
		}

		$outside_paths = array();
		foreach($paths as $param_name => $resolved){
			if(strpos($resolved . '/', $this->project_path . '/') !== 0 && $resolved !== $this->project_path){
				if(strpos($resolved . '/', $this->user_home_dir . '/') === 0 || $resolved === $this->user_home_dir){
					$outside_paths[$param_name] = $resolved;
				}else{
					return array(
						'type' => 'blocked',
						'tool_name' => $tool_name,
						'key' => '',
						'summary' => 'Blocked: path outside home directory',
						'detail' => $resolved,
						'detail_label' => 'Blocked path'
					);
				}
			}
		}

		if(empty($outside_paths)){
			return null;
		}

		$first_param = array_keys($outside_paths)[0];
		$first_path = $outside_paths[$first_param];
		$key = 'path:' . $first_path;

		$summary = 'Access file outside project directory';
		if($tool_name === 'write_file' || $tool_name === 'edit_file' || $tool_name === 'search_replace'){
			$summary = 'Modify file outside project directory';
		}elseif($tool_name === 'archive'){
			$summary = 'Archive files outside project directory';
		}elseif($tool_name === 'file_download'){
			$summary = 'Download file outside project directory';
		}

		return array(
			'type' => 'path',
			'tool_name' => $tool_name,
			'key' => $key,
			'summary' => $summary,
			'detail' => $first_path,
			'detail_label' => 'Path',
			'paths' => $outside_paths
		);
	}

	public function check_permission($tool_name, array $params, AIConversation $conversation){
		$request = $this->build_permission_request($tool_name, $params);
		if($request === null || $request['type'] === 'blocked'){
			return $request;
		}

		if($request['type'] !== 'power' && $conversation->has_permission($request['key'])){
			return null;
		}

		if($request['type'] === 'path'){
			$paths = $request['paths'];
			foreach($paths as $resolved){
				if($this->is_path_allowed_by_directory($resolved, $conversation)){
					return null;
				}
			}
		}

		return $request;
	}

	public function is_outside_project_tool($tool_name, array $params){
		$request = $this->build_permission_request($tool_name, $params);
		return $request !== null && $request['type'] === 'path';
	}

	private function is_path_allowed_by_directory($resolved_path, AIConversation $conversation){
		$permissions = $conversation->get_permissions();
		$parts = explode('/', trim($resolved_path, '/'));
		$current = '';
		foreach($parts as $part){
			$current .= '/' . $part;
			$key = 'path:' . $current;
			if(isset($permissions[$key]) && $permissions[$key] === 'allow_always'){
				return true;
			}
		}
		return false;
	}

	private function resolve_param_path($path){
		if(empty($path) || !is_string($path)){
			return null;
		}
		if(strpos($path, 'ai/settings.json.php') !== false){
			return null;
		}
		$base = (strpos($path, '/') === 0) ? '' : $this->project_path . '/';
		$resolved = $this->normalize_path($base . ltrim($path, '/'));
		$real = realpath($resolved);
		if($real !== false){
			return $real;
		}
		return $resolved;
	}

	private function normalize_path($path){
		$path = str_replace('\\', '/', $path);
		$parts = explode('/', $path);
		$resolved = array();
		foreach($parts as $part){
			if($part === '..'){
				array_pop($resolved);
			}elseif($part !== '.' && $part !== ''){
				$resolved[] = $part;
			}
		}
		return '/' . implode('/', $resolved);
	}
}
