<?php

namespace PloverCRM\Modules\Integrations\Endpoints;

use Exception;
use PloverCRM\Core\Api\AbstractEndpoint;
use PloverCRM\Modules\Integrations\Services\GoogleAdsConnectionService;
use PloverCRM\Modules\Integrations\Services\GoogleAdsLeadUploadStatusService;
use PloverCRM\Modules\Integrations\Services\GoogleAdsService;
use PloverCRM\Modules\Integrations\Services\MetaCapiConnectionService;
use WP_REST_Request;

class ConnectionsBootstrapEndpoint extends AbstractEndpoint
{
    public function getRoute(): string
    {
        return '/connections/bootstrap';
    }

    public function getMethod()
    {
        return 'GET';
    }

    public function checkPermission(WP_REST_Request $request)
    {
        return $this->checkAuthenticatedCapability($request, 'manage_options');
    }

    public function handle(WP_REST_Request $request)
    {
        return $this->success([
            'google' => $this->buildGooglePayload($request),
            'meta' => [
                'connections' => array_map(
                    static fn($connection) => $connection->toPublicArray(),
                    MetaCapiConnectionService::getAllConnections(false)
                ),
            ],
        ]);
    }

    private function buildGooglePayload(WP_REST_Request $request): array
    {
        $config = get_option('plover_crm_google_config', []);
        $isAuthenticated = !empty($config['refresh_token']);
        $hasDeveloperToken = !empty($config['developer_token']);

        return [
            'oauth' => [
                'isAuthenticated' => $isAuthenticated,
                'hasDeveloperToken' => $hasDeveloperToken,
                'connectUrl' => $this->getGoogleConnectUrl($request),
            ],
            'accounts' => $this->getGoogleAccounts($config, $isAuthenticated, $hasDeveloperToken),
            'connections' => array_map(
                [$this, 'serializeGoogleConnection'],
                GoogleAdsConnectionService::getAllConnections(false)
            ),
        ];
    }

    private function serializeGoogleConnection($connection): array
    {
        return array_merge($connection->toPublicArray(), [
            'lead_upload_status' => GoogleAdsLeadUploadStatusService::forConnection($connection, true),
        ]);
    }

    private function getGoogleAccounts(array $config, bool $isAuthenticated, bool $hasDeveloperToken): array
    {
        if (!$isAuthenticated || !$hasDeveloperToken) {
            return [
                'items' => [],
                'error' => null,
            ];
        }

        try {
            $service = new GoogleAdsService();

            return [
                'items' => $service->listAccessibleCustomers($config['developer_token']),
                'error' => null,
            ];
        } catch (Exception $exception) {
            return [
                'items' => [],
                'error' => $exception->getMessage(),
            ];
        }
    }

    private function getGoogleConnectUrl(WP_REST_Request $request): string
    {
        $appRedirect = $this->resolveConnectionsAppUrl($request);
        $signature = hash_hmac('sha256', $appRedirect, wp_salt('auth'));
        $returnUrl = add_query_arg([
            'app_redirect' => rawurlencode($appRedirect),
            'redirect_signature' => $signature,
        ], rest_url('plover-crm/v1/google/oauth/callback'));

        return 'https://webplover.com/api/google/auth.php?return_url=' . rawurlencode($returnUrl);
    }

    private function resolveConnectionsAppUrl(WP_REST_Request $request): string
    {
        $origin = $this->getOriginFromRequest($request);
        if ($origin !== null) {
            return rtrim($origin, '/') . '/connections';
        }

        return home_url('/plover-crm/connections/');
    }

    private function getOriginFromRequest(WP_REST_Request $request): ?string
    {
        $forwardedAppOrigin = trim((string) $request->get_header('x-plover-app-origin'));
        if ($this->isAllowedAppOrigin($forwardedAppOrigin)) {
            return untrailingslashit($forwardedAppOrigin);
        }

        $originHeader = trim((string) $request->get_header('origin'));
        if ($this->isAllowedAppOrigin($originHeader)) {
            return untrailingslashit($originHeader);
        }

        $refererHeader = trim((string) $request->get_header('referer'));
        if ($refererHeader !== '') {
            $parts = wp_parse_url($refererHeader);
            $scheme = isset($parts['scheme']) ? strtolower((string) $parts['scheme']) : '';
            $host = (string) ($parts['host'] ?? '');

            if (in_array($scheme, ['http', 'https'], true) && $host !== '') {
                $origin = $scheme . '://' . $host;

                if (!empty($parts['port'])) {
                    $origin .= ':' . (int) $parts['port'];
                }

                if ($this->isAllowedAppOrigin($origin)) {
                    return $origin;
                }
            }
        }

        return null;
    }

    private function isAllowedAppOrigin(string $origin): bool
    {
        if ($origin === '') {
            return false;
        }

        $parts = wp_parse_url($origin);
        $scheme = isset($parts['scheme']) ? strtolower((string) $parts['scheme']) : '';
        $host = (string) ($parts['host'] ?? '');

        return in_array($scheme, ['http', 'https'], true) && $host !== '';
    }
}
