<?php

namespace App\Tests\Controller\Api;

use App\Controller\Api\ApiAccountController;
use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;

class ApiAccountControllerTest extends TestCase
{
    private const SECRET = 'test_secret';

    private function createController(): ApiAccountController
    {
        $reflection = new \ReflectionClass(ApiAccountController::class);
        $controller = $reflection->newInstanceWithoutConstructor();

        $prop = $reflection->getProperty('appSecret');
        $prop->setValue($controller, self::SECRET);

        // Set the container to null-like state — we only use the trait helpers
        $containerProp = (new \ReflectionClass(\Symfony\Bundle\FrameworkBundle\Controller\AbstractController::class))->getProperty('container');
        $containerProp->setValue($controller, new \Symfony\Component\DependencyInjection\Container());

        return $controller;
    }

    private function createEm(?User $user): EntityManagerInterface
    {
        $repo = $this->createMock(UserRepository::class);
        $repo->method('findOneBy')->willReturn($user);

        $em = $this->createMock(EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($repo);

        return $em;
    }

    private function createUser(int $id, string $email, ?string $stripeAccountId = null): User
    {
        $user = $this->createMock(User::class);
        $user->method('getId')->willReturn($id);
        $user->method('getEmail')->willReturn($email);
        $user->method('getStripeAccountId')->willReturn($stripeAccountId);

        return $user;
    }

    private function makeRequest(string $email = '', string $secret = self::SECRET): Request
    {
        $request = Request::create('/api/account/lookup', 'POST', [], [], [], [], json_encode(['email' => $email]));
        $request->headers->set('X-App-Secret', $secret);
        $request->headers->set('Content-Type', 'application/json');

        return $request;
    }

    public function testLookupSuccess(): void
    {
        $controller = $this->createController();
        $user = $this->createUser(42, 'test@example.com', 'acct_123');
        $em = $this->createEm($user);

        $response = $controller->lookup($this->makeRequest('test@example.com'), $em);

        self::assertSame(200, $response->getStatusCode());
        $data = json_decode($response->getContent(), true);
        self::assertTrue($data['success']);
        self::assertSame(42, $data['data']['id']);
        self::assertSame('acct_123', $data['data']['stripeAccountId']);
    }

    public function testLookupSuccessWithoutStripe(): void
    {
        $controller = $this->createController();
        $user = $this->createUser(10, 'user@example.com');
        $em = $this->createEm($user);

        $response = $controller->lookup($this->makeRequest('user@example.com'), $em);

        $data = json_decode($response->getContent(), true);
        self::assertTrue($data['success']);
        self::assertSame(10, $data['data']['id']);
        self::assertNull($data['data']['stripeAccountId']);
    }

    public function testLookupInvalidSecret(): void
    {
        $controller = $this->createController();
        $em = $this->createEm(null);

        $response = $controller->lookup($this->makeRequest('test@example.com', 'wrong_secret'), $em);

        self::assertSame(401, $response->getStatusCode());
        $data = json_decode($response->getContent(), true);
        self::assertFalse($data['success']);
        self::assertSame('Secret invalide.', $data['error']);
    }

    public function testLookupEmptySecret(): void
    {
        $controller = $this->createController();
        $em = $this->createEm(null);

        $response = $controller->lookup($this->makeRequest('test@example.com', ''), $em);

        self::assertSame(401, $response->getStatusCode());
    }

    public function testLookupMissingEmail(): void
    {
        $controller = $this->createController();
        $em = $this->createEm(null);

        $response = $controller->lookup($this->makeRequest(''), $em);

        self::assertSame(400, $response->getStatusCode());
        $data = json_decode($response->getContent(), true);
        self::assertSame('Email requis.', $data['error']);
    }

    public function testLookupUserNotFound(): void
    {
        $controller = $this->createController();
        $em = $this->createEm(null);

        $response = $controller->lookup($this->makeRequest('notfound@example.com'), $em);

        self::assertSame(404, $response->getStatusCode());
        $data = json_decode($response->getContent(), true);
        self::assertSame('Utilisateur introuvable.', $data['error']);
    }
}
