package de.cannamanage.api.controller;

import de.cannamanage.api.dto.club.UpdateClubRequest;
import de.cannamanage.domain.entity.Club;
import de.cannamanage.domain.entity.TenantContext;
import de.cannamanage.domain.enums.ClubStatus;
import de.cannamanage.service.ClubService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class ClubControllerTest {

    @Mock
    private ClubService clubService;

    @InjectMocks
    private ClubController clubController;

    private UUID tenantId;
    private Club club;

    @BeforeEach
    void setUp() {
        tenantId = UUID.randomUUID();
        TenantContext.setCurrentTenant(tenantId);

        club = new Club();
        club.setId(UUID.randomUUID());
        club.setTenantId(tenantId);
        club.setName("Green Garden Club");
        club.setRegistrationNumber("REG-2024-001");
        club.setContactEmail("info@greengardenclub.de");
        club.setContactPhone("+49 30 12345678");
        club.setAddressStreet("Hanfweg 42");
        club.setAddressCity("Berlin");
        club.setAddressPostalCode("10115");
        club.setAddressState("Berlin");
        club.setFoundedDate(LocalDate.of(2024, 7, 1));
        club.setMaxPreventionOfficers(2);
        club.setAllowedEmailPattern(".*@greengardenclub\\.de");
        club.setStatus(ClubStatus.ACTIVE);
        club.setCreatedAt(Instant.now());
        club.setLicenseNumber("LIC-001");
    }

    @AfterEach
    void tearDown() {
        TenantContext.clear();
    }

    @Test
    void getMyClub_returnsClubResponse() {
        when(clubService.getClubByTenantId(tenantId)).thenReturn(club);

        ResponseEntity<?> response = clubController.getMyClub();

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).isNotNull();
        verify(clubService).getClubByTenantId(tenantId);
    }

    @Test
    void updateMyClub_updatesAndReturns() {
        UpdateClubRequest request = new UpdateClubRequest(
                "Updated Club", "REG-NEW", "new@club.de", "+49111",
                "Newstreet 1", "Hamburg", "20095", "Hamburg",
                LocalDate.of(2024, 1, 1), 3, ".*@club\\.de"
        );
        when(clubService.updateClub(
                eq(tenantId), eq("Updated Club"), eq("REG-NEW"),
                eq("new@club.de"), eq("+49111"),
                eq("Newstreet 1"), eq("Hamburg"), eq("20095"), eq("Hamburg"),
                eq(LocalDate.of(2024, 1, 1)), eq(3), eq(".*@club\\.de")
        )).thenReturn(club);

        ResponseEntity<?> response = clubController.updateMyClub(request);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).isNotNull();
    }

    @Test
    void getMyClubStats_returnsStats() {
        ClubService.ClubStats stats = new ClubService.ClubStats(
                50, 42, 5, 4, 120, new BigDecimal("1500.50"), 8, 2
        );
        when(clubService.getClubStats(tenantId)).thenReturn(stats);

        ResponseEntity<?> response = clubController.getMyClubStats();

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).isNotNull();
        verify(clubService).getClubStats(tenantId);
    }
}
