<?php

namespace App\Service;

use Stripe\StripeClient;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

/**
 * @codeCoverageIgnore
 */
class StripeWebhookService
{
    private StripeClient $stripe;

    /** Evenements legers (statuts, metadata) */
    private const LIGHT_EVENTS = [
        'customer.created',
        'customer.updated',
        'customer.deleted',
        'product.created',
        'product.updated',
        'price.created',
        'price.updated',
        'invoice.created',
        'invoice.finalized',
        'invoice.payment_succeeded',
        'invoice.payment_failed',
        'customer.subscription.created',
        'customer.subscription.updated',
        'customer.subscription.deleted',
    ];

    /** Evenements instantanes (paiements, actions critiques) */
    private const INSTANT_EVENTS = [
        'checkout.session.completed',
        'checkout.session.expired',
        'payment_intent.succeeded',
        'payment_intent.payment_failed',
        'charge.succeeded',
        'charge.failed',
        'charge.refunded',
        'charge.dispute.created',
        'invoice.paid',
        'invoice.payment_failed',
        'customer.subscription.trial_will_end',
        'customer.subscription.deleted',
    ];

    /** Evenements Connect legers */
    private const CONNECT_LIGHT_EVENTS = [
        'account.updated',
        'account.application.authorized',
        'account.application.deauthorized',
        'transfer.created',
        'transfer.updated',
        'payout.created',
        'payout.paid',
        'payout.failed',
    ];

    /** Evenements Connect instantanes */
    private const CONNECT_INSTANT_EVENTS = [
        'payment_intent.succeeded',
        'payment_intent.payment_failed',
        'charge.succeeded',
        'charge.failed',
        'charge.refunded',
        'checkout.session.completed',
    ];

    public function __construct(
        #[Autowire(env: 'STRIPE_SK')] string $stripeSecret,
    ) {
        $this->stripe = new StripeClient($stripeSecret);
    }

    /**
     * Cree les 4 webhooks Stripe (main light/instant + connect light/instant).
     *
     * @return array{created: list<array{type: string, url: string, id: string, status: string, secret?: string}>, errors: list<string>}
     */
    public function createAllWebhooks(string $baseUrl): array
    {
        $created = [];
        $errors = [];

        $webhooks = [
            ['url' => $baseUrl.'/webhooks/stripe/main/light', 'events' => self::LIGHT_EVENTS, 'connect' => false, 'type' => 'Main Light'],
            ['url' => $baseUrl.'/webhooks/stripe/main/instant', 'events' => self::INSTANT_EVENTS, 'connect' => false, 'type' => 'Main Instant'],
            ['url' => $baseUrl.'/webhooks/stripe/connect/light', 'events' => self::CONNECT_LIGHT_EVENTS, 'connect' => true, 'type' => 'Connect Light'],
            ['url' => $baseUrl.'/webhooks/stripe/connect/instant', 'events' => self::CONNECT_INSTANT_EVENTS, 'connect' => true, 'type' => 'Connect Instant'],
        ];

        foreach ($webhooks as $wh) {
            try {
                $existing = $this->findWebhookByUrl($wh['url']);
                if (null !== $existing) {
                    $created[] = ['type' => $wh['type'], 'url' => $wh['url'], 'id' => $existing->id, 'status' => 'exists'];

                    continue;
                }

                $endpoint = $this->stripe->webhookEndpoints->create([
                    'url' => $wh['url'],
                    'enabled_events' => $wh['events'],
                    'connect' => $wh['connect'],
                    'description' => 'CRM E-Cosplay - '.$wh['type'],
                ]);

                $created[] = ['type' => $wh['type'], 'url' => $wh['url'], 'id' => $endpoint->id, 'status' => 'created', 'secret' => $endpoint->secret];
            } catch (\Throwable $e) {
                $errors[] = $wh['type'].': '.$e->getMessage();
            }
        }

        return ['created' => $created, 'errors' => $errors];
    }

    /**
     * Liste tous les webhooks existants.
     *
     * @return list<array{id: string, url: string, status: string, events: list<string>, connect: bool}>
     */
    public function listWebhooks(): array
    {
        $endpoints = $this->stripe->webhookEndpoints->all(['limit' => 100]);
        $result = [];

        foreach ($endpoints->data as $ep) {
            $result[] = [
                'id' => $ep->id,
                'url' => $ep->url,
                'status' => $ep->status,
                'events' => $ep->enabled_events ?? [],
                'connect' => 'connect' === ($ep->application ?? ''),
            ];
        }

        return $result;
    }

    /**
     * Supprime un webhook par son ID.
     */
    public function deleteWebhook(string $webhookId): bool
    {
        try {
            $this->stripe->webhookEndpoints->delete($webhookId);

            return true;
        } catch (\Throwable) {
            return false;
        }
    }

    private function findWebhookByUrl(string $url): ?object
    {
        $endpoints = $this->stripe->webhookEndpoints->all(['limit' => 100]);

        foreach ($endpoints->data as $ep) {
            if ($ep->url === $url) {
                return $ep;
            }
        }

        return null;
    }
}
