<?php

namespace GemBoards\Classes;

use GemBoards\Settings\Base;
use GemBoards\Utils\Helper;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class PermissionResolver {

	public static function basic_api_permission_check() {
		if ( ! current_user_can( 'read' ) ) {
			return new \WP_Error(
				'rest_forbidden_context',
				esc_html__( 'Sorry, you are not allowed to access this API.', 'gemboards' ),
				array( 'status' => rest_authorization_required_code() )
			);
		}

		return true;
	}

	public static function can( $permissionKey, array $request, $user_id = null ): bool {
		$user_id = $user_id ?: get_current_user_id();
		if ( ! $user_id ) {
			return false;
		}

		if ( current_user_can( 'manage_gemboards' ) ) {
			return true;
		}

		$project_id = self::resolve_project_context( $request );
		if ( ! $project_id ) {
			return false;
		}

		$cache_key   = "project_role_$project_id";
		$cache_group = Helper::ROLES_TABLE_NAME;
		$role        = wp_cache_get( $cache_key, $cache_group );

		if ( false === $role ) {
			global $wpdb;
			// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
			$role = $wpdb->get_var( $wpdb->prepare(
				"SELECT role FROM {$wpdb->prefix}gemboards_roles WHERE user_id = %d AND object_id = %d AND object_type = 'project' LIMIT 1",
				$user_id,
				$project_id
			) );
			// phpcs:enable
			wp_cache_set( $cache_key, $role, $cache_group );
		}

		if ( ! $role ) {
			return false;
		}

		$settings = Base::get_settings_saved_data();
		$matrix   = $settings['permissions'][ $permissionKey ] ?? [];

		return ! empty( $matrix[ $role ] );
	}

	private static function resolve_project_context( array $request ): ?int {
		global $wpdb;

		if ( ! empty( $request['project_id'] ) ) {
			return (int) $request['project_id'];
		}

		if ( ! empty( $request['board_id'] ) ) {
			$board_id    = absint($request['board_id']);
			$cache_key   = "project_id_from_board_$board_id";
			$cache_group = Helper::BOARDS_TABLE_NAME;
			$project_id  = wp_cache_get( $cache_key, $cache_group );
			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "SELECT project_id FROM {$wpdb->prefix}gemboards_boards WHERE id = %d LIMIT 1", $board_id )
				);
				// phpcs:enable
				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		if ( ! empty( $request['column_id'] ) ) {
			$column_id   = absint($request['column_id']);
			$cache_key   = "project_id_from_column_$column_id";
			$cache_group = Helper::BOARD_COLUMN_TABLE_NAME;
			$project_id  = wp_cache_get( $cache_key, $cache_group );

			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "
                    SELECT b.project_id
                    FROM {$wpdb->prefix}gemboards_columns c
                    INNER JOIN {$wpdb->prefix}gemboards_boards b ON b.id = c.board_id
                    WHERE c.id = %d
                    LIMIT 1
                ", $column_id )
				);
				// phpcs:enable
				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		if ( ! empty( $request['card_id'] ) ) {
			$cache_key   = "project_id_from_card_{$request['card_id']}";
			$cache_group = Helper::BOARD_CARD_TABLE_NAME;
			$project_id  = wp_cache_get( $cache_key, $cache_group );

			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "
                    SELECT b.project_id
                    FROM {$wpdb->prefix}gemboards_cards c
                    INNER JOIN {$wpdb->prefix}gemboards_boards b ON b.id = c.board_id
                    WHERE c.id = %d
                    LIMIT 1
                ", (int) $request['card_id'] )
				);
				// phpcs:enable

				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		if ( ! empty( $request['sprint_id'] ) ) {
			$cache_key   = "project_id_from_sprint_{$request['sprint_id']}";
			$cache_group = Helper::BOARD_CARD_TABLE_NAME;
			$project_id  = wp_cache_get( $cache_key, $cache_group );

			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "
                    SELECT b.project_id
                    FROM {$wpdb->prefix}gemboards_cards c
                    INNER JOIN {$wpdb->prefix}gemboards_boards b ON b.id = c.board_id
                    WHERE c.sprint_id = %d
                    LIMIT 1
                ", (int) $request['sprint_id'] )
				);
				// phpcs:enable

				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		if ( ! empty( $request['folder_id'] ) ) {
			$cache_key   = "project_id_from_folder_{$request['folder_id']}";
			$cache_group = Helper::FOLDERS_TABLE_NAME;
			$project_id  = wp_cache_get( $cache_key, $cache_group );

			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "SELECT project_id FROM {$wpdb->prefix}gemboards_folders WHERE id = %d LIMIT 1", (int) $request['folder_id'] )
				);
				// phpcs:enable
				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		if ( ! empty( $request['task_id'] ) ) {
			$task_id     = absint($request['task_id']);
			$cache_key   = "project_id_from_task_$task_id";
			$cache_group = Helper::BOARD_CARD_TABLE_NAME;
			$project_id  = wp_cache_get( $cache_key, $cache_group );

			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "
                    SELECT b.project_id
                    FROM {$wpdb->prefix}gemboards_cards c
                    INNER JOIN {$wpdb->prefix}gemboards_boards b ON b.id = c.board_id
                    WHERE c.task_id = %d
                    LIMIT 1
                ", $task_id )
				);
				// phpcs:enable

				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		if ( ! empty( $request['role_id'] ) ) {
			$cache_key   = "project_id_from_role_{$request['role_id']}";
			$cache_group = 'gemboards_roles';
			$project_id  = wp_cache_get( $cache_key, $cache_group );

			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "
                    SELECT r.object_id
                    FROM {$wpdb->prefix}gemboards_roles r
                    WHERE r.id = %d AND r.object_type = 'project'
                    LIMIT 1
                ", (int) $request['role_id'] )
				);
				// phpcs:enable

				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		if ( ! empty( $request['invitation_id'] ) ) {
			$cache_key   = "project_id_from_invitation_{$request['invitation_id']}";
			$cache_group = 'gemboards_user_invitations';
			$project_id  = wp_cache_get( $cache_key, $cache_group );

			if ( false === $project_id ) {
				// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
				$project_id = $wpdb->get_var(
					$wpdb->prepare( "
                    SELECT ui.object_id
                    FROM {$wpdb->prefix}gemboards_user_invitations ui
                    WHERE ui.id = %d AND ui.object_type = 'project'
                    LIMIT 1
                ", (int) $request['invitation_id'] )
				);
				// phpcs:enable

				if ( $project_id ) {
					wp_cache_set( $cache_key, $project_id, $cache_group );
				}
			}

			if ( $project_id ) {
				return (int) $project_id;
			}
		}

		return apply_filters( 'gemboards/resolve_project_context', null, $request );
	}
}
