<?php

namespace App\Service;

use App\Entity\Billet;
use App\Entity\User;
use Stripe\Event;
use Stripe\Exception\SignatureVerificationException;
use Stripe\StripeClient;
use Stripe\Webhook;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

class StripeService
{
    private StripeClient $stripe;

    public function __construct(
        #[Autowire(env: 'STRIPE_SK')] private string $stripeSecret,
        #[Autowire(env: 'STRIPE_WEBHOOK_SECRET')] private string $webhookSecret,
        #[Autowire(env: 'STRIPE_WEBHOOK_SECRET_CONNECT')] private string $webhookSecretConnect,
        #[Autowire(env: 'OUTSIDE_URL')] private string $outsideUrl,
    ) {
        $this->stripe = new StripeClient($this->stripeSecret);
    }

    public function verifyWebhookSignature(string $payload, string $signature): ?Event
    {
        try {
            return Webhook::constructEvent($payload, $signature, $this->webhookSecret);
        } catch (SignatureVerificationException) {
            return null;
        }
    }

    public function verifyConnectWebhookSignature(string $payload, string $signature): ?Event
    {
        try {
            return Webhook::constructEvent($payload, $signature, $this->webhookSecretConnect);
        } catch (SignatureVerificationException) {
            return null;
        }
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function deleteAccount(string $accountId): void
    {
        $this->stripe->accounts->delete($accountId);
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function createAccountConnect(User $user): string
    {
        $account = $this->stripe->accounts->create([
            'type' => 'express',
            'country' => 'FR',
            'email' => $user->getEmail(),
            'capabilities' => [
                'card_payments' => ['requested' => true],
                'transfers' => ['requested' => true],
            ],
            'business_type' => \in_array('ROLE_ORGANIZER', $user->getRoles(), true) ? 'company' : 'individual',
            'business_profile' => [
                'name' => $user->getCompanyName(),
                'url' => $this->outsideUrl,
            ],
        ]);

        return $account->id;
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function createAccountLink(string $accountId): string
    {
        $link = $this->stripe->accountLinks->create([
            'account' => $accountId,
            'refresh_url' => $this->outsideUrl.'/stripe/connect/refresh',
            'return_url' => $this->outsideUrl.'/stripe/connect/return',
            'type' => 'account_onboarding',
        ]);

        return $link->url;
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function createLoginLink(string $accountId): string
    {
        $link = $this->stripe->accounts->createLoginLink($accountId);

        return $link->url;
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function createProduct(Billet $billet, string $connectedAccountId): string
    {
        $product = $this->stripe->products->create([
            'name' => $billet->getName(),
            'description' => $billet->getDescription(),
            'default_price_data' => [
                'currency' => 'eur',
                'unit_amount' => $billet->getPriceHT(),
            ],
        ], ['stripe_account' => $connectedAccountId]);

        return $product->id;
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function updateProduct(Billet $billet, string $connectedAccountId): void
    {
        $this->stripe->products->update($billet->getStripeProductId(), [
            'name' => $billet->getName(),
            'description' => $billet->getDescription(),
        ], ['stripe_account' => $connectedAccountId]);
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function deleteProduct(string $productId, string $connectedAccountId): void
    {
        $this->stripe->products->update($productId, [
            'active' => false,
        ], ['stripe_account' => $connectedAccountId]);
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     */
    public function createBillingCheckoutSession(User $user): string
    {
        $session = $this->stripe->checkout->sessions->create([
            'mode' => 'subscription',
            'customer_email' => $user->getEmail(),
            'line_items' => [[
                'price_data' => [
                    'currency' => 'eur',
                    'unit_amount' => $user->getBillingAmount(),
                    'recurring' => ['interval' => 'month'],
                    'product_data' => [
                        'name' => 'Abonnement E-Ticket',
                    ],
                ],
                'quantity' => 1,
            ]],
            'metadata' => [
                'user_id' => (string) $user->getId(),
            ],
            'success_url' => $this->outsideUrl.'/mon-compte/abonnement/succes',
            'cancel_url' => $this->outsideUrl.'/mon-compte',
        ]);

        return $session->url;
    }

    /**
     * @codeCoverageIgnore Simple getter
     */
    public function getClient(): StripeClient
    {
        return $this->stripe;
    }

    /**
     * @codeCoverageIgnore Requires live Stripe API
     *
     * @return array{charges_enabled: bool, payouts_enabled: bool}
     */
    public function retrieveAccountStatus(string $accountId): array
    {
        $account = $this->stripe->accounts->retrieve($accountId);

        return [
            'charges_enabled' => (bool) $account->charges_enabled,
            'payouts_enabled' => (bool) $account->payouts_enabled,
        ];
    }
}
