<?php
/**
 * Media API
 *
 * Custom FleekDash REST endpoints for media management:
 *  - POST /fleekdash/v1/media/batch-move
 *  - GET  /fleekdash/v1/media/folder-stats
 *  - POST /fleekdash/v1/media/batch-delete
 *
 * Standard WordPress media CRUD is already available via /wp/v2/media.
 * Folder taxonomy CRUD is available via /wp/v2/media_folder.
 *
 * @package FleekDash\API
 * @since   2.3.2
 */

namespace FleekDash\API;

use FleekDash\Core\AuthMiddleware;
use FleekDash\Services\MediaFolderService;
use FleekDash\Services\MediaFolderUserColorsService;

defined('ABSPATH') || exit;

class MediaAPI
{
    private const API_NAMESPACE = 'fleekdash/v1';
    private const MSG_NOT_AUTHENTICATED = 'Not authenticated';
    private const MSG_AUTHENTICATION_ERROR = 'Authentication error';

    private MediaFolderService $service;

    public function __construct()
    {
        $this->service = new MediaFolderService();
    }

    public function registerRoutes(): void
    {
        \register_rest_route(self::API_NAMESPACE, '/media/batch-move', [
            'methods'             => 'POST',
            'callback'            => [$this, 'batchMove'],
            'permission_callback' => [$this, 'checkPermissions'],
            'args'                => [],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/media/type-counts', [
            'methods'             => 'GET',
            'callback'            => [$this, 'typeCounts'],
            'permission_callback' => [$this, 'checkPermissions'],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/media/folder-stats', [
            'methods'             => 'GET',
            'callback'            => [$this, 'folderStats'],
            'permission_callback' => [$this, 'checkPermissions'],
            'args'                => [
                'media_type' => [
                    'required'    => false,
                    'type'        => 'string',
                    'enum'        => ['all', 'image', 'video', 'audio', 'application'],
                    'description' => 'Filter folder counts by media type.',
                ],
            ],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/media/batch-delete', [
            'methods'             => 'POST',
            'callback'            => [$this, 'batchDelete'],
            'permission_callback' => [$this, 'checkPermissions'],
            'args'                => [
                'media_ids' => [
                    'required'    => true,
                    'type'        => 'array',
                    'items'       => ['type' => 'integer'],
                    'description' => 'Array of attachment IDs to delete.',
                ],
                'force' => [
                    'required'    => false,
                    'type'        => 'boolean',
                    'default'     => true,
                    'description' => 'Whether to bypass trash and delete permanently.',
                ],
            ],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/media/search-count', [
            'methods'             => 'GET',
            'callback'            => [$this, 'searchCount'],
            'permission_callback' => [$this, 'checkPermissions'],
            'args'                => [
                'search'      => [
                    'required'    => true,
                    'type'        => 'string',
                    'description' => 'Search term for media items.',
                ],
                'folder_id'   => [
                    'required'    => false,
                    'type'        => 'integer',
                    'default'     => 0,
                    'description' => 'When > 0, returns in_folder count for items in this folder.',
                ],
                'media_type'  => [
                    'required'    => false,
                    'type'        => 'string',
                    'enum'        => ['all', 'image', 'video', 'audio', 'application'],
                    'default'     => 'all',
                    'description' => 'Filter by media type.',
                ],
            ],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/media/folders/reorder', [
            'methods'             => 'POST',
            'callback'            => [$this, 'foldersReorder'],
            'permission_callback' => [$this, 'checkPermissions'],
            'args'                => [
                'parent_id' => [
                    'required'    => true,
                    'type'        => 'integer',
                    'description' => 'Parent folder term ID (0 for root).',
                ],
                'ordered_ids' => [
                    'required'    => true,
                    'type'        => 'array',
                    'items'       => ['type' => 'integer'],
                    'description' => 'Sibling folder IDs in desired order.',
                ],
            ],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/media/folder-color', [
            'methods'             => 'POST',
            'callback'            => [$this, 'folderColorUpdate'],
            'permission_callback' => [$this, 'checkPermissions'],
            'args'                => [],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/media/folder-colors/merge', [
            'methods'             => 'POST',
            'callback'            => [$this, 'folderColorsMerge'],
            'permission_callback' => [$this, 'checkPermissions'],
            'args'                => [],
        ]);
    }

    public function checkPermissions(): bool
    {
        return true;
    }

    public function batchMove(\WP_REST_Request $request): \WP_REST_Response
    {
        try {
            $auth = AuthMiddleware::check('authenticated');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => self::MSG_NOT_AUTHENTICATED,
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
            ]);
        }

        $json = $request->get_json_params();
        if (\is_array($json)) {
            $media_ids = $json['media_ids'] ?? $request->get_param('media_ids');
            $folder_id = $json['folder_id'] ?? $request->get_param('folder_id');
        } else {
            $media_ids = $request->get_param('media_ids');
            $folder_id = $request->get_param('folder_id');
        }

        if (!\is_array($media_ids)) {
            $media_ids = [];
        }
        $media_ids = array_values(array_map('intval', array_filter($media_ids, 'is_numeric')));

        $folder_id = ($folder_id !== null && $folder_id !== '' && (int) $folder_id > 0)
            ? (int) $folder_id
            : null;

        $result = $this->service->batchMove($media_ids, $folder_id);

        return \rest_ensure_response([
            'success' => $result['failed'] === 0,
            'data'    => $result,
        ]);
    }

    public function folderStats(\WP_REST_Request $request): \WP_REST_Response
    {
        try {
            $auth = AuthMiddleware::check('authenticated');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => self::MSG_NOT_AUTHENTICATED,
                    'data'    => [
                        'folders'       => [],
                        'unsorted'      => 0,
                        'total'         => 0,
                        'folder_colors' => [],
                    ],
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
                'data'    => [
                    'folders'       => [],
                    'unsorted'      => 0,
                    'total'         => 0,
                    'folder_colors' => [],
                ],
            ]);
        }

        $media_type = $request->get_param('media_type');
        $stats      = $this->service->getFolderStats($media_type);
        $colors     = new MediaFolderUserColorsService();
        $stats['folder_colors'] = $colors->getMapForCurrentUser();

        return \rest_ensure_response([
            'success' => true,
            'data'    => $stats,
        ]);
    }

    public function folderColorUpdate(\WP_REST_Request $request): \WP_REST_Response
    {
        try {
            $auth = AuthMiddleware::check('authenticated');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => self::MSG_NOT_AUTHENTICATED,
                    'data'    => ['colors' => []],
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
                'data'    => ['colors' => []],
            ]);
        }

        $json      = $request->get_json_params();
        $folder_id = 0;
        $color_raw = null;
        if (\is_array($json)) {
            if (isset($json['folder_id'])) {
                $folder_id = (int) $json['folder_id'];
            }
            if (\array_key_exists('color_id', $json)) {
                $color_raw = $json['color_id'];
            }
        }
        if ($folder_id <= 0) {
            $folder_id = (int) $request->get_param('folder_id');
        }
        if ($color_raw === null) {
            $color_raw = $request->get_param('color_id');
        }

        $color_id = null;
        if ($color_raw !== null && $color_raw !== '') {
            $color_id = \sanitize_key((string) $color_raw);
        }

        $svc    = new MediaFolderUserColorsService();
        $result = $svc->setColorForCurrentUser($folder_id, $color_id);

        return \rest_ensure_response([
            'success' => $result['success'],
            'message' => $result['message'],
            'data'    => ['colors' => $result['colors']],
        ]);
    }

    public function folderColorsMerge(\WP_REST_Request $request): \WP_REST_Response
    {
        try {
            $auth = AuthMiddleware::check('authenticated');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => self::MSG_NOT_AUTHENTICATED,
                    'data'    => ['colors' => [], 'merged' => 0],
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
                'data'    => ['colors' => [], 'merged' => 0],
            ]);
        }

        $json   = $request->get_json_params();
        $colors = [];
        if (\is_array($json) && isset($json['colors']) && \is_array($json['colors'])) {
            foreach ($json['colors'] as $k => $v) {
                if (!\is_string($k) && !\is_int($k)) {
                    continue;
                }
                $colors[(string) $k] = (string) $v;
            }
        }

        $svc    = new MediaFolderUserColorsService();
        $result = $svc->mergeMapsForCurrentUser($colors);

        return \rest_ensure_response([
            'success' => $result['success'],
            'data'    => [
                'colors' => $result['colors'],
                'merged' => $result['merged'],
            ],
        ]);
    }

    public function typeCounts(\WP_REST_Request $request): \WP_REST_Response // NOSONAR php:S1172 - Required by WP REST API callback signature
    {
        try {
            $auth = AuthMiddleware::check('authenticated');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => self::MSG_NOT_AUTHENTICATED,
                    'data'    => ['all' => 0, 'image' => 0, 'video' => 0, 'audio' => 0, 'application' => 0],
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
                'data'    => ['all' => 0, 'image' => 0, 'video' => 0, 'audio' => 0, 'application' => 0],
            ]);
        }

        $counts = $this->service->getCountsByType();

        return \rest_ensure_response([
            'success' => true,
            'data'    => $counts,
        ]);
    }

    public function batchDelete(\WP_REST_Request $request): \WP_REST_Response
    {
        try {
            $auth = AuthMiddleware::check('admin');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => 'Admin privileges required',
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
            ]);
        }

        $media_ids = $request->get_param('media_ids');
        $force     = (bool) $request->get_param('force');

        $result = $this->service->batchDelete($media_ids, $force);

        return \rest_ensure_response([
            'success' => $result['failed'] === 0,
            'data'    => $result,
        ]);
    }

    public function searchCount(\WP_REST_Request $request): \WP_REST_Response
    {
        try {
            $auth = AuthMiddleware::check('authenticated');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => self::MSG_NOT_AUTHENTICATED,
                    'data'    => ['total' => 0, 'in_folder' => 0],
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
                'data'    => ['total' => 0, 'in_folder' => 0],
            ]);
        }

        $search     = \sanitize_text_field((string) $request->get_param('search'));
        $folder_id  = (int) $request->get_param('folder_id');
        $media_type = $request->get_param('media_type');

        $folder_param = $folder_id > 0 ? $folder_id : null;
        $result       = $this->service->getSearchCounts($search, $folder_param, $media_type);

        return \rest_ensure_response([
            'success' => true,
            'data'    => $result,
        ]);
    }

    public function foldersReorder(\WP_REST_Request $request): \WP_REST_Response
    {
        try {
            $auth = AuthMiddleware::check('authenticated');
            if (!$auth['authenticated']) {
                return \rest_ensure_response([
                    'success' => false,
                    'message' => self::MSG_NOT_AUTHENTICATED,
                ]);
            }
        } catch (\Exception $e) {
            return \rest_ensure_response([
                'success' => false,
                'message' => self::MSG_AUTHENTICATION_ERROR,
            ]);
        }

        $parent_id   = (int) $request->get_param('parent_id');
        $ordered_ids = $request->get_param('ordered_ids');
        if (!\is_array($ordered_ids)) {
            $ordered_ids = [];
        }
        $ordered_ids = array_map('intval', array_values($ordered_ids));

        $result = $this->service->reorderFolders($parent_id, $ordered_ids);

        return \rest_ensure_response([
            'success' => $result['success'],
            'data'    => $result,
        ]);
    }
}

\add_action('rest_api_init', function () {
    $api = new MediaAPI();
    $api->registerRoutes();
});
