import {beforeEach, describe, expect, it} from 'vitest';
import {createTestWrapper, mockData, mockServer} from '../../utils/msw-helpers';
import {renderHook, waitFor} from '@testing-library/react';
import {usePostNewsletterStats} from '@src/hooks/use-post-newsletter-stats';

describe('usePostNewsletterStats', () => {
    const testPostId = 'test-post-id';

    beforeEach(() => {
        mockServer.setup(); // Basic setup with defaults
    });

    it('calculates stats correctly from post email data', async () => {
        const postWithEmailStats = mockData.post({
            id: testPostId,
            email: {
                email_count: 1000,
                opened_count: 300
            },
            count: {
                clicks: 50
            }
        });

        mockServer.setup({
            posts: [postWithEmailStats]
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            expect(result.current.stats).toEqual({
                sent: 1000,
                opened: 300,
                clicked: 50,
                openedRate: 0.3, // 300/1000
                clickedRate: 0.05 // 50/1000
            });
        });
    });

    it('returns zero stats when post has no email data', async () => {
        const postWithoutEmail = mockData.post({
            id: testPostId
            // No email or count data
        });

        mockServer.setup({
            posts: [postWithoutEmail]
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            expect(result.current.stats).toEqual({
                sent: 0,
                opened: 0,
                clicked: 0,
                openedRate: 0,
                clickedRate: 0
            });
        });
    });

    it('calculates average newsletter performance correctly', async () => {
        const newsletterStats = [
            {post_id: 'post1', open_rate: 0.25, click_rate: 0.03},
            {post_id: 'post2', open_rate: 0.35, click_rate: 0.07},
            {post_id: 'post3', open_rate: 0.30, click_rate: 0.05}
        ];

        mockServer.setup({
            posts: [mockData.post({id: testPostId})],
            newsletterBasicStats: newsletterStats,
            newsletterClickStats: newsletterStats
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            // Average: (0.25 + 0.35 + 0.30) / 3 = 0.30
            // Average: (0.03 + 0.07 + 0.05) / 3 = 0.05
            expect(result.current.averageStats).toEqual({
                openedRate: 0.30,
                clickedRate: 0.05
            });
        });
    });

    it('prevents division by zero in rate calculations', async () => {
        const postWithClicksButNoEmails = mockData.post({
            id: testPostId,
            email: {
                email_count: 0,
                opened_count: 5 // Impossible but testing edge case
            },
            count: {
                clicks: 10
            }
        });

        mockServer.setup({
            posts: [postWithClicksButNoEmails]
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            expect(result.current.stats.openedRate).toBe(0);
            expect(result.current.stats.clickedRate).toBe(0);
            expect(Number.isNaN(result.current.stats.openedRate)).toBe(false);
            expect(Number.isNaN(result.current.stats.clickedRate)).toBe(false);
        });
    });

    it('handles missing newsletter comparison data gracefully', async () => {
        mockServer.setup({
            posts: [mockData.post({id: testPostId})],
            newsletterBasicStats: [],
            newsletterClickStats: []
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            expect(result.current.averageStats).toEqual({
                openedRate: 0,
                clickedRate: 0
            });
        });
    });

    it('provides top performing links sorted by click count', async () => {
        const linksData = [
            {
                post_id: testPostId,
                link: {link_id: 'link1', to: 'https://popular.com', from: 'post', edited: false},
                count: {clicks: 25}
            },
            {
                post_id: testPostId,
                link: {link_id: 'link2', to: 'https://www.another.com', from: 'post', edited: false},
                count: {clicks: 15}
            }
        ];

        mockServer.setup({
            posts: [mockData.post({id: testPostId})],
            links: linksData
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            // Should be sorted by click count (highest first) and URLs cleaned
            expect(result.current.topLinks).toHaveLength(2);
            expect(result.current.topLinks[0].count).toBe(25);
            expect(result.current.topLinks[1].count).toBe(15);

            // Verify URL cleaning and display formatting happens
            expect(result.current.topLinks[0].link.title).toBe('popular.com');
            expect(result.current.topLinks[1].link.title).toBe('another.com');
        });
    });

    it('calculates precise rates with fractional results', async () => {
        const postWithPrecisionChallenge = mockData.post({
            id: testPostId,
            email: {
                email_count: 7,
                opened_count: 2
            },
            count: {
                clicks: 1
            }
        });

        mockServer.setup({
            posts: [postWithPrecisionChallenge]
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            // 2/7 = 0.2857142857142857... (JavaScript precision)
            expect(result.current.stats.openedRate).toBeCloseTo(2 / 7, 10);
            // 1/7 = 0.14285714285714285... (JavaScript precision)
            expect(result.current.stats.clickedRate).toBeCloseTo(1 / 7, 10);

            // Ensure calculations return valid numbers (not NaN or Infinity)
            expect(Number.isFinite(result.current.stats.openedRate)).toBe(true);
            expect(Number.isFinite(result.current.stats.clickedRate)).toBe(true);
        });
    });

    it('handles enterprise scale numbers correctly', async () => {
        const enterprisePost = mockData.post({
            id: testPostId,
            email: {
                email_count: 1000000,
                opened_count: 250000
            },
            count: {
                clicks: 12500
            }
        });

        mockServer.setup({
            posts: [enterprisePost]
        });

        const {result} = renderHook(() => usePostNewsletterStats(testPostId), {
            wrapper: createTestWrapper()
        });

        await waitFor(() => {
            expect(result.current.stats).toEqual({
                sent: 1000000,
                opened: 250000,
                clicked: 12500,
                openedRate: 0.25, // 250000/1000000
                clickedRate: 0.0125 // 12500/1000000
            });

            // Ensure calculations maintain precision at scale
            expect(Number.isFinite(result.current.stats.openedRate)).toBe(true);
            expect(Number.isFinite(result.current.stats.clickedRate)).toBe(true);
        });
    });
});
