<?php

namespace EasyLinkAutomations\HTTP\Controllers\Actions;

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

use EasyLinkAutomations\HTTP\Request\Request;
use EasyLinkAutomations\HTTP\Response;
use EasyLinkAutomations\Models\Connection;

/**
 * Controller for Notion related API calls.
 * Handles fetching databases and database properties for dynamic field loading.
 */
final class NotionController
{
    private const API_BASE    = 'https://api.notion.com/v1';
    private const API_VERSION = '2022-06-28';

    /**
     * Get list of databases accessible to the integration.
     *
     * Fetches from POST /search with database filter.
     */
    public function databases(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');

        if (!$connectionId) {
            return Response::error('Connection ID is required', 400);
        }

        $token = Connection::getAccessToken($connectionId);
        if (empty($token)) {
            return Response::error('Invalid connection or token expired', 401);
        }

        $response = wp_remote_request(self::API_BASE . '/search', [
            'method'  => 'POST',
            'headers' => [
                'Content-Type'   => 'application/json',
                'Authorization'  => 'Bearer ' . $token,
                'Notion-Version' => self::API_VERSION,
            ],
            'body'    => wp_json_encode([
                'filter'    => ['property' => 'object', 'value' => 'database'],
                'page_size' => 100,
            ]),
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return Response::error('Failed to fetch databases: ' . $response->get_error_message());
        }

        $body       = json_decode(wp_remote_retrieve_body($response), true);
        $statusCode = wp_remote_retrieve_response_code($response);

        if ($statusCode < 200 || $statusCode >= 300) {
            return Response::error('Notion API error: ' . ($body['message'] ?? 'Unknown error'));
        }

        $databases = [];
        foreach ($body['results'] ?? [] as $db) {
            $titleParts = $db['title'] ?? [];
            $title      = '';
            foreach ($titleParts as $part) {
                $title .= $part['plain_text'] ?? $part['text']['content'] ?? '';
            }
            $title = trim($title) ?: 'Untitled';

            $databases[] = [
                'value' => $db['id'] ?? '',
                'label' => $title,
            ];
        }

        return Response::success(['databases' => $databases]);
    }

    /**
     * Get properties of a specific Notion database for field mapping.
     *
     * Fetches from GET /databases/{database_id} and returns property names and types.
     */
    public function databaseProperties(Request $request): Response
    {
        $connectionId = (int) $request->get('connection_id');
        $databaseId   = trim((string) $request->get('database_id'));

        if (!$connectionId) {
            return Response::error('Connection ID is required', 400);
        }

        if (empty($databaseId)) {
            return Response::error('Database ID is required', 400);
        }

        $token = Connection::getAccessToken($connectionId);
        if (empty($token)) {
            return Response::error('Invalid connection or token expired', 401);
        }

        $url      = self::API_BASE . '/databases/' . rawurlencode($databaseId);
        $response = wp_remote_get($url, [
            'headers' => [
                'Authorization'  => 'Bearer ' . $token,
                'Notion-Version' => self::API_VERSION,
            ],
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return Response::error('Failed to fetch database properties: ' . $response->get_error_message());
        }

        $body       = json_decode(wp_remote_retrieve_body($response), true);
        $statusCode = wp_remote_retrieve_response_code($response);

        if ($statusCode < 200 || $statusCode >= 300) {
            return Response::error('Notion API error: ' . ($body['message'] ?? 'Unknown error'));
        }

        // Computed / read-only property types that cannot be set by the user
        $readOnlyTypes = ['formula', 'rollup', 'created_time', 'last_edited_time', 'created_by', 'last_edited_by', 'unique_id', 'verification'];

        $columns = [];
        foreach ($body['properties'] ?? [] as $propName => $prop) {
            $type = $prop['type'] ?? '';

            // Skip read-only / computed properties
            if (in_array($type, $readOnlyTypes, true)) {
                continue;
            }

            $column = [
                'value' => $propName,
                'label' => $propName . ' (' . $type . ')',
            ];

            // Title property is always required — every database page needs one
            if ($type === 'title') {
                $column['required'] = true;
            }

            $columns[] = $column;
        }

        // Sort: required columns first, then alphabetically
        usort($columns, static function (array $a, array $b): int {
            $aReq = (int) ($a['required'] ?? 0);
            $bReq = (int) ($b['required'] ?? 0);
            if ($aReq !== $bReq) {
                return $bReq - $aReq;
            }
            return strcmp($a['label'], $b['label']);
        });

        return Response::success(['columns' => $columns]);
    }
}
