package de.cannamanage.api.integration;

import de.cannamanage.domain.entity.Member;
import de.cannamanage.domain.entity.User;
import org.junit.jupiter.api.*;
import org.springframework.http.ResponseEntity;

import java.time.LocalDate;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * Integration test: Portal session-based authentication.
 * Verifies form login, session cookie, own-data access, and access denial.
 */
class PortalIntegrationTest extends AbstractIntegrationTest {

    private UUID tenantId;
    private UUID memberId;

    @BeforeEach
    void setUp() {
        tenantId = createTestClub("Portal Test Club");

        // Create a member directly in DB
        Member member = createMemberDirectly(tenantId, "Portal", "User",
                "portal@test.de", LocalDate.of(1990, 5, 15));
        memberId = member.getId();

        // Create a MEMBER user linked to the member
        createMemberUser(tenantId, memberId, "portal@test.de", "PortalPass123!");
    }

    @Test
    @DisplayName("Portal login with valid credentials returns 200 + session cookie")
    void portalLogin_validCredentials_returnsOk() {
        // Portal login is form-based — POST with x-www-form-urlencoded
        ResponseEntity<String> response = restClient().post()
                .uri("/portal/login")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .body("username=portal@test.de&password=PortalPass123!")
                .retrieve()
                .toEntity(String.class);

        assertThat(response.getStatusCode().value()).isEqualTo(200);
        assertThat(response.getBody()).contains("ok");

        // Session cookie should be set
        assertThat(response.getHeaders().get("Set-Cookie")).isNotNull();
    }

    @Test
    @DisplayName("Portal dashboard accessible with session")
    void portalDashboard_withSession_returns200() {
        // Login first
        ResponseEntity<String> loginResponse = restClient().post()
                .uri("/portal/login")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .body("username=portal@test.de&password=PortalPass123!")
                .retrieve()
                .toEntity(String.class);

        // Extract session cookie
        String sessionCookie = loginResponse.getHeaders().getFirst("Set-Cookie");
        if (sessionCookie != null) {
            String cookieValue = sessionCookie.split(";")[0];

            ResponseEntity<String> dashResponse = restClient().get()
                    .uri("/portal/dashboard")
                    .header("Cookie", cookieValue)
                    .retrieve()
                    .toEntity(String.class);

            assertThat(dashResponse.getStatusCode().value()).isEqualTo(200);
        }
    }

    @Test
    @DisplayName("Portal quota endpoint returns member's quota data")
    void portalQuota_withSession_returns200() {
        ResponseEntity<String> loginResponse = restClient().post()
                .uri("/portal/login")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .body("username=portal@test.de&password=PortalPass123!")
                .retrieve()
                .toEntity(String.class);

        String sessionCookie = loginResponse.getHeaders().getFirst("Set-Cookie");
        if (sessionCookie != null) {
            String cookieValue = sessionCookie.split(";")[0];

            ResponseEntity<String> quotaResponse = restClient().get()
                    .uri("/portal/quota")
                    .header("Cookie", cookieValue)
                    .retrieve()
                    .toEntity(String.class);

            assertThat(quotaResponse.getStatusCode().value()).isEqualTo(200);
        }
    }

    @Test
    @DisplayName("Portal access without session returns unauthorized/redirect")
    void portalAccess_withoutSession_returnsUnauthorized() {
        ResponseEntity<String> response = restClient().get()
                .uri("/portal/dashboard")
                .retrieve()
                .toEntity(String.class);

        assertThat(response.getStatusCode().value()).isIn(401, 403, 302);
    }

    @Test
    @DisplayName("Portal login with invalid credentials returns 401")
    void portalLogin_invalidCredentials_returns401() {
        ResponseEntity<String> response = restClient().post()
                .uri("/portal/login")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .body("username=portal@test.de&password=WrongPassword!")
                .retrieve()
                .toEntity(String.class);

        assertThat(response.getStatusCode().value()).isEqualTo(401);
    }
}
