<?php
/**
 * Permission Request Controller
 *
 * REST API endpoints for users to request permission overrides.
 *
 * @package FleekDash\API
 * @since 2.3.0
 */

namespace FleekDash\API;

use FleekDash\Core\AuthMiddleware;
use FleekDash\Core\PermissionManager;
use FleekDash\Core\PermissionOverrideManager;
use FleekDash\Models\Notifications;
use FleekDash\Realtime\RealtimeEventOutboxService;

defined('ABSPATH') || exit;

class PermissionRequestController extends \WP_REST_Controller {
    protected $namespace = 'fleekdash/v1';
    protected $restBase = 'permissions/requests';

    /**
     * Register routes
     */
    public function register_routes(): void {
        register_rest_route($this->namespace, '/' . $this->restBase, [
            [
                'methods' => \WP_REST_Server::CREATABLE,
                'callback' => [$this, 'create_request'],
                'permission_callback' => [$this, 'check_permissions'],
                'args' => [
                    'permission_id' => [
                        'required' => true,
                        'type' => 'string',
                        'validate_callback' => 'rest_validate_request_arg',
                    ],
                    'reason' => [
                        'required' => true,
                        'type' => 'string',
                        'sanitize_callback' => 'sanitize_textarea_field',
                        'validate_callback' => 'rest_validate_request_arg',
                    ],
                ],
            ],
        ]);

        register_rest_route($this->namespace, '/' . $this->restBase . '/(?P<id>\d+)/approve', [
            [
                'methods' => \WP_REST_Server::EDITABLE,
                'callback' => [$this, 'approve_request'],
                'permission_callback' => [$this, 'check_permissions'],
            ],
        ]);
    }

    /**
     * Check permissions for the request
     *
     * @param \WP_REST_Request $request
     * @return bool
     */
    public function check_permissions(\WP_REST_Request $request): bool {
        $path = $request->get_route();

        // Approval endpoint requires admin level
        if (strpos($path, '/approve') !== false) {
            $auth_check = AuthMiddleware::check('admin');
            return $auth_check['authenticated'];
        }

        // Creation endpoint requires authenticated level
        $auth_check = AuthMiddleware::check('authenticated');
        return $auth_check['authenticated'];
    }

    /**
     * Create a permission request
     */
    public function create_request(\WP_REST_Request $request): \WP_REST_Response {
        $user_id = \get_current_user_id();
        $user = \get_userdata($user_id);

        if (!$user) {
            return new \WP_REST_Response([
                'success' => false,
                'message' => 'User not found',
            ], 404);
        }

        $permission_id = $request->get_param('permission_id');
        $reason = $request->get_param('reason');

        if (!PermissionManager::has($permission_id)) {
            return new \WP_REST_Response([
                'success' => false,
                'message' => 'Invalid permission ID',
            ], 400);
        }

        $result = $this->createPermissionRequestNotification($user, $user_id, $permission_id, $reason);
        return new \WP_REST_Response($result['body'], $result['status']);
    }

    /**
     * Build notification data and create notification; returns response body and status.
     *
     * @param \WP_User $user
     * @param int $user_id
     * @param string $permission_id
     * @param string $reason
     * @return array{body: array, status: int}
     */
    private function createPermissionRequestNotification(
        $user,
        int $user_id,
        string $permission_id,
        string $reason
    ): array {
        $permission_node = PermissionManager::get($permission_id);
        $permission_label = $permission_node['label'] ?? $permission_id;

        $notification_data = [
            'type' => 'permission_request',
            'subject' => sprintf('Permission Request: %s', $permission_label),
            'message' => sprintf(
                'User %s is requesting permission for: %s. Reason: %s',
                $user->display_name,
                $permission_label,
                $reason
            ),
            'source' => 'permission_system',
            'source_id' => $user_id,
            'sender_info' => [
                'user_id' => $user_id,
                'user_name' => $user->display_name,
                'user_email' => $user->user_email,
            ],
            'actions' => [
                [
                    'label' => 'Approve',
                    'action' => 'approve_permission',
                    'primary' => true,
                    'data' => ['user_id' => $user_id, 'permission_id' => $permission_id],
                ],
                [
                    'label' => 'Deny',
                    'action' => 'deny_permission',
                    'data' => ['user_id' => $user_id, 'permission_id' => $permission_id],
                ],
            ],
            'meta' => [
                'permission_id' => $permission_id,
                'user_id' => $user_id,
                'reason' => $reason,
            ],
            'status' => 'unread',
        ];

        try {
            $notification_id = Notifications::create($notification_data);
        } catch (\Throwable $e) {
            return [
                'body' => [
                    'success' => false,
                    'message' => 'Failed to create notification. Please try again.',
                ],
                'status' => 500,
            ];
        }

        if (empty($notification_id) || !is_numeric($notification_id)) {
            return [
                'body' => [
                    'success' => false,
                    'message' => 'Failed to save request. Please try again.',
                ],
                'status' => 500,
            ];
        }

        $admin_email = \get_option('admin_email');
        $approve_url = \admin_url('admin.php?page=fleekdash#/users/overrides?request=' . $notification_id);
        $email_subject = sprintf('[FleekDash] Permission Request from %s', $user->display_name);
        $email_body = sprintf(
            "User %s (%s) is requesting access to: %s\n\nReason: %s\n\nYou can approve this request here: %s",
            $user->display_name,
            $user->user_email,
            $permission_label,
            $reason,
            $approve_url
        );
        \wp_mail($admin_email, $email_subject, $email_body);
        RealtimeEventOutboxService::enqueue('notifications.created', [
            'message' => sprintf(
                'New permission request from %s for %s',
                $user->display_name,
                $permission_label
            ),
            'notification_id' => (int) $notification_id,
            'type' => 'permission_request',
        ], [
            'scope' => 'all',
        ]);

        return [
            'body' => [
                'success' => true,
                'message' => 'Request sent successfully',
                'notification_id' => (int) $notification_id,
            ],
            'status' => 201,
        ];
    }

    /**
     * Approve a permission request (placeholder for future extension)
     */
    public function approve_request(\WP_REST_Request $request): \WP_REST_Response {
        $id = (int) $request->get_param('id');
        $notification = Notifications::find($id);

        $response_data = [
            'success' => false,
            'message' => 'Failed to approve permission',
        ];
        $status = 500;

        if (!$notification || $notification['type'] !== 'permission_request') {
            $response_data['message'] = 'Request not found';
            $status = 404;
        } elseif (!isset($notification['meta']['user_id']) || !isset($notification['meta']['permission_id'])) {
            $response_data['message'] = 'Invalid notification data';
            $status = 400;
        } else {
            $override = PermissionOverrideManager::create([
                'user_id' => $notification['meta']['user_id'],
                'permission_id' => $notification['meta']['permission_id'],
                'override_type' => 'ALLOW',
                'reason' => 'Approved via permission request',
                'created_by' => \get_current_user_id(),
            ]);

            if ($override) {
                Notifications::resolve($id);
                $response_data = [
                    'success' => true,
                    'message' => 'Permission approved',
                ];
                $status = 200;
            }
        }

        return new \WP_REST_Response($response_data, $status);
    }
}
