<?php

namespace Give\Subscriptions\ViewModels;

use Give\API\REST\V3\Routes\Donors\ValueObjects\DonorAnonymousMode;
use Give\Framework\PaymentGateways\Contracts\Subscription\SubscriptionTransactionsSynchronizable;
use Give\Framework\PaymentGateways\PaymentGatewayRegister;
use Give\Framework\Support\Facades\Str;
use Give\Subscriptions\Models\Subscription;

/**
 * @since 4.8.0
 */
class SubscriptionViewModel
{
    private Subscription $subscription;

    private DonorAnonymousMode $anonymousMode;

    private bool $includeSensitiveData = false;

    /**
     * @since 4.8.0
     */
    public function __construct(Subscription $subscription)
    {
        $this->subscription = $subscription;
    }

    /**
     * @since 4.8.0
     */
    public function includeSensitiveData(bool $includeSensitiveData = true): SubscriptionViewModel
    {
        $this->includeSensitiveData = $includeSensitiveData;

        return $this;
    }

    /**
    * @since 4.8.0
    */
    public function anonymousMode(DonorAnonymousMode $mode): SubscriptionViewModel
    {
        $this->anonymousMode = $mode;

        return $this;
    }

    /**
     * @since 4.14.0 lastName should return only the first letter when sensitive data is not included
     * @since 4.10.0 added campaignId
     * @since 4.8.0
     */
    public function exports(): array
    {
        $donor = $this->subscription->donor;

        $data = array_merge(
            $this->subscription->toArray(),
            [
                'firstName' => $donor ? $donor->firstName : '',
                'lastName' => $donor ? $donor->lastName : '',
                'gateway' => $this->getGatewayDetails(),
                'projectedAnnualRevenue' => $this->subscription->projectedAnnualRevenue(),
                'campaignId' => $this->subscription->campaign ? $this->subscription->campaign->id : null,
            ]
        );

        if (!$this->includeSensitiveData) {
            $sensitiveDataExcluded = [
                'transactionId',
                'gatewaySubscriptionId',
                'lastName',
            ];

            foreach ($sensitiveDataExcluded as $propertyName) {
                switch ($propertyName) {
                    case 'lastName':
                        $data[$propertyName] = Str::substr($data[$propertyName], 0, 1);
                        break;
                    default:
                        $data[$propertyName] = '';
                        break;
                }
            }
        }

        if (isset($this->anonymousMode) && $this->anonymousMode->isRedacted() && $this->subscription->donor->isAnonymous()) {
            $anonymousDataRedacted = [
                'donorId',
                'firstName',
                'lastName',
            ];

            foreach ($anonymousDataRedacted as $propertyName) {
                switch ($propertyName) {
                    case 'donorId':
                        $data[$propertyName] = 0;
                        break;
                    default:
                        $data[$propertyName] = __('anonymous', 'give');
                        break;
                }
            }
        }

        return $data;
    }

    /**
     * @since 4.14.0 Return gateway details without subscriptionUrl when sensitive data is not included
     * @since 4.10.0 Return null if subscription URL is not available
     * @since 4.8.0
     */
    private function getGatewayDetails(): ?array
    {
        if (empty($this->subscription->gatewayId) || !give(PaymentGatewayRegister::class)->hasPaymentGateway($this->subscription->gatewayId)) {
            return null;
        }

        if (!$this->includeSensitiveData) {
            return $this->subscription->gateway()->toArray();
        }

        $subscriptionUrl = $this->subscription->gateway()->gatewayDashboardSubscriptionUrl($this->subscription);

        return array_merge(
            $this->subscription->gateway()->toArray(),
            [
                'subscriptionUrl' => $subscriptionUrl ?: null,
                'canSync' => $this->subscription->gateway()->subscriptionModule instanceof SubscriptionTransactionsSynchronizable
            ]
        );
    }
}
