<?php

declare(strict_types=1);

namespace App\Tests\Functional\Controller;

use App\Entity\Device;
use App\Enum\DeviceModel;
use App\Enum\Orientation;
use App\Tests\Functional\AppWebTestCase;

class SetupControllerTest extends AppWebTestCase
{
    private const MAC = 'AA:BB:CC:00:11:22';

    // S-01: anonymous GET /setup/{mac} → 200 (shows login/register form)
    public function test_setup_index_anonymous_renders(): void
    {
        $this->client->request('GET', '/setup/' . self::MAC);
        $this->assertResponseIsSuccessful();
    }

    // S-02: authenticated with named device → redirects to spa (/)
    public function test_setup_index_authenticated_named_device_redirects_to_spa(): void
    {
        $user = $this->createUser('setup02@example.com');

        $device = new Device();
        $device->setMac(self::MAC);
        $device->setName('Living Room');
        $device->setUser($user);
        $this->em()->persist($device);
        $this->em()->flush();

        $this->loginAs($user);
        $this->client->request('GET', '/setup/' . self::MAC);

        $this->assertResponseRedirects('/');
    }

    // S-03: authenticated with no existing device (new link) → redirects to configure
    public function test_setup_index_authenticated_new_device_redirects_to_configure(): void
    {
        $user = $this->createUser('setup03@example.com');
        $this->loginAs($user);

        $this->client->request('GET', '/setup/' . self::MAC);

        $this->assertResponseRedirects('/setup/' . self::MAC . '/configure');
    }

    // S-04: POST /setup/{mac}/register with valid data → creates user, links device, redirects to configure
    public function test_setup_register_creates_user_and_redirects_to_configure(): void
    {
        $this->client->request('POST', '/setup/' . self::MAC . '/register', [
            'registration_form' => [
                'email'         => 'setupnew@example.com',
                'plainPassword' => [
                    'first'  => 'securepass123',
                    'second' => 'securepass123',
                ],
            ],
        ]);

        $this->assertResponseRedirects('/setup/' . self::MAC . '/configure');
    }

    // S-05: POST /setup/{mac}/configure with valid name → saves device, redirects to spa
    public function test_setup_configure_saves_name_and_redirects_to_spa(): void
    {
        $user = $this->createUser('setup05@example.com');

        $device = new Device();
        $device->setMac(self::MAC);
        $device->setUser($user);
        $this->em()->persist($device);
        $this->em()->flush();

        $deviceId = $device->getId();

        $this->loginAs($user);
        $this->client->request('POST', '/setup/' . self::MAC . '/configure', [
            'name'                      => 'Kitchen Frame',
            'orientation'               => 'landscape',
            'rotation_interval_minutes' => '1440',
            'uniqueness_window'         => '10',
        ]);

        $this->assertResponseRedirects('/');

        $this->em()->clear();
        $saved = $this->em()->find(Device::class, $deviceId);
        $this->assertSame('Kitchen Frame', $saved->getName());
    }

    // S-06: POST /setup/{mac}/login with valid credentials → redirects to configure
    public function test_login_valid_credentials_redirects_to_configure(): void
    {
        $this->createUser('setuplogin@example.com', 'testpass');

        $this->client->request('POST', '/setup/' . self::MAC . '/login', [
            '_username' => 'setuplogin@example.com',
            '_password' => 'testpass',
        ]);

        $this->assertResponseRedirects('/setup/' . self::MAC . '/configure');
    }

    // S-07: POST /setup/{mac}/login with wrong password → redirects to index
    public function test_login_invalid_credentials_redirects_to_index(): void
    {
        $this->createUser('setupbadlogin@example.com', 'testpass');

        $this->client->request('POST', '/setup/' . self::MAC . '/login', [
            '_username' => 'setupbadlogin@example.com',
            '_password' => 'wrongpass',
        ]);

        $this->assertResponseRedirects('/setup/' . self::MAC);
    }

    // S-08: authenticated GET /setup/{mac}/configure → 200
    public function test_configure_get_renders_form(): void
    {
        $user = $this->createUser('setupconfigget@example.com');

        $device = new Device();
        $device->setMac(self::MAC);
        $device->setUser($user);
        $this->em()->persist($device);
        $this->em()->flush();

        $this->loginAs($user);
        $this->client->request('GET', '/setup/' . self::MAC . '/configure');

        $this->assertResponseIsSuccessful();
    }

    // S-09: POST /setup/{mac}/configure with empty name → 200 (re-renders form with error)
    public function test_configure_post_empty_name_renders_error(): void
    {
        $user = $this->createUser('setupconfigerr@example.com');

        $device = new Device();
        $device->setMac(self::MAC);
        $device->setUser($user);
        $this->em()->persist($device);
        $this->em()->flush();

        $this->loginAs($user);
        $this->client->request('POST', '/setup/' . self::MAC . '/configure', [
            'name'        => '',
            'orientation' => 'landscape',
        ]);

        $this->assertResponseIsSuccessful();
    }

    // S-10: POST /setup/{mac}/register with invalid form data → re-renders registration page
    public function test_setup_register_invalid_form_renders_page(): void
    {
        // Valid email (avoids TypeError) but mismatched passwords → form is invalid
        $this->client->request('POST', '/setup/' . self::MAC . '/register', [
            'registration_form' => [
                'email'         => 'setup-invalid@example.com',
                'plainPassword' => [
                    'first'  => 'password123',
                    'second' => 'different456',
                ],
            ],
        ]);

        // Symfony 7 returns 422 for submitted-but-invalid forms
        $this->assertResponseStatusCodeSame(422);
    }
}
