package de.cannamanage.service;

import de.cannamanage.domain.entity.Club;
import de.cannamanage.service.model.report.MemberListReport;
import de.cannamanage.service.model.report.MonthlyReport;
import de.cannamanage.service.model.report.RecallReport;
import de.cannamanage.domain.enums.MemberStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

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

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

class PdfReportGeneratorTest {

    private PdfReportGenerator generator;
    private Club club;

    @BeforeEach
    void setUp() {
        generator = new PdfReportGenerator();
        club = new Club();
        club.setName("Grüne Freunde e.V.");
    }

    @Test
    void testRenderMonthlyReport_validPdf() {
        MonthlyReport report = new MonthlyReport();
        report.setMonth(YearMonth.of(2026, 3));
        report.setTotalDistributions(42);
        report.setTotalGrams(new BigDecimal("210.50"));
        report.setUniqueMembers(15);
        report.setAveragePerMember(new BigDecimal("14.03"));
        report.setTopStrains(List.of(
                new MonthlyReport.StrainSummary("White Widow", new BigDecimal("80.00"), 18),
                new MonthlyReport.StrainSummary("Amnesia Haze", new BigDecimal("60.00"), 12)
        ));
        report.setDailyBreakdown(List.of(
                new MonthlyReport.DailyEntry(LocalDate.of(2026, 3, 1), new BigDecimal("15.00"), 3),
                new MonthlyReport.DailyEntry(LocalDate.of(2026, 3, 2), new BigDecimal("8.50"), 2)
        ));

        byte[] pdf = generator.renderMonthlyReport(report, club);

        assertThat(pdf).isNotEmpty();
        assertThat(pdf).startsWith("%PDF".getBytes());
    }

    @Test
    void testRenderMemberList_validPdf() {
        MemberListReport report = new MemberListReport();
        report.setGeneratedAt(Instant.now());

        MemberListReport.MemberEntry entry = new MemberListReport.MemberEntry();
        entry.setId(UUID.randomUUID());
        entry.setFirstName("Max");
        entry.setLastName("Mustermann");
        entry.setMembershipNumber("M-001");
        entry.setStatus(MemberStatus.ACTIVE);
        entry.setJoinDate(LocalDate.of(2025, 6, 1));
        entry.setTotalDistributions(12);
        entry.setLastDistributionDate(Instant.parse("2026-03-15T10:00:00Z"));

        report.setMembers(List.of(entry));

        byte[] pdf = generator.renderMemberList(report, club);

        assertThat(pdf).isNotEmpty();
        assertThat(pdf).startsWith("%PDF".getBytes());
    }

    @Test
    void testRenderRecallReport_validPdf() {
        RecallReport report = new RecallReport();
        report.setBatchId(UUID.randomUUID());
        report.setStrainName("Northern Lights");
        report.setBatchNumber("BATCH-2026-007");
        report.setReceivedDate(LocalDate.of(2026, 2, 20));
        report.setTotalGramsDistributed(new BigDecimal("45.00"));

        RecallReport.AffectedMember am = new RecallReport.AffectedMember();
        am.setMemberId(UUID.randomUUID());
        am.setFirstName("Anna");
        am.setLastName("Schmidt");
        am.setDistributionDate(Instant.parse("2026-03-05T12:00:00Z"));
        am.setGrams(new BigDecimal("5.00"));

        report.setAffectedMembers(List.of(am));

        byte[] pdf = generator.renderRecallReport(report, club);

        assertThat(pdf).isNotEmpty();
        assertThat(pdf).startsWith("%PDF".getBytes());
    }

    @Test
    void testRenderMonthlyReport_emptyReport() {
        MonthlyReport report = new MonthlyReport();
        report.setMonth(YearMonth.of(2026, 1));
        report.setTotalDistributions(0);
        report.setTotalGrams(BigDecimal.ZERO);
        report.setUniqueMembers(0);
        report.setAveragePerMember(BigDecimal.ZERO);
        report.setTopStrains(List.of());
        report.setDailyBreakdown(List.of());

        byte[] pdf = generator.renderMonthlyReport(report, club);

        assertThat(pdf).isNotEmpty();
        assertThat(pdf).startsWith("%PDF".getBytes());
    }
}
