import NewSubscribersCadence from '@src/views/Stats/Growth/components/new-subscribers-cadence';
import moment from 'moment';
import {beforeEach, describe, expect, it, vi} from 'vitest';
import {mockSuccess} from '@tryghost/admin-x-framework/test/hook-testing-utils';
import {render, screen} from '@testing-library/react';

// Mock the API hooks
vi.mock('@tryghost/admin-x-framework/api/stats', () => ({
    useSubscriptionStats: vi.fn()
}));

vi.mock('@tryghost/admin-x-framework/api/tiers', () => ({
    useBrowseTiers: vi.fn()
}));

// Mock date helpers from @tryghost/shade/app
vi.mock('@tryghost/shade/app', async () => {
    const actual = await vi.importActual('@tryghost/shade/app');
    return {
        ...actual,
        getRangeDates: vi.fn((range: number) => {
            // Mock date range calculation
            const endDate = moment('2024-01-31');
            const startDate = moment('2024-01-01');
            if (range === 30) {
                startDate.subtract(30, 'days');
            }
            return {startDate, endDate, timezone: 'UTC'};
        }),
        formatQueryDate: vi.fn(date => date.format('YYYY-MM-DD'))
    };
});

vi.mock('@tryghost/shade/utils', async () => {
    const actual = await vi.importActual('@tryghost/shade/utils');
    return {
        ...actual,
        formatNumber: vi.fn((value: number) => value.toString())
    };
});

import {useBrowseTiers} from '@tryghost/admin-x-framework/api/tiers';
import {useSubscriptionStats} from '@tryghost/admin-x-framework/api/stats';

const mockedUseSubscriptionStats = useSubscriptionStats as ReturnType<typeof vi.fn>;
const mockedUseBrowseTiers = useBrowseTiers as ReturnType<typeof vi.fn>;

describe('NewSubscribersCadence Component', () => {
    beforeEach(() => {
        vi.clearAllMocks();

        // Default mock for tiers - single tier
        mockSuccess(mockedUseBrowseTiers, {
            tiers: [
                {id: 'tier-1', name: 'Premium', type: 'paid', active: true}
            ]
        });
    });

    it('renders with mixed monthly/yearly signups and calculates percentages correctly', () => {
        // Mock stats with signups data (date-filtered data)
        const mockSubscriptionData = {
            stats: [
                {date: '2024-01-15', tier: 'tier-1', cadence: 'month', signups: 45, cancellations: 5, count: 100},
                {date: '2024-01-15', tier: 'tier-1', cadence: 'year', signups: 15, cancellations: 2, count: 50},
                {date: '2024-01-20', tier: 'tier-1', cadence: 'month', signups: 30, cancellations: 3, count: 110},
                {date: '2024-01-20', tier: 'tier-1', cadence: 'year', signups: 10, cancellations: 1, count: 55}
            ],
            meta: {
                totals: [
                    {tier: 'tier-1', cadence: 'month', count: 110},
                    {tier: 'tier-1', cadence: 'year', count: 55}
                ]
            }
        };

        mockSuccess(mockedUseSubscriptionStats, mockSubscriptionData);

        render(<NewSubscribersCadence isLoading={false} range={30} />);

        // Check that the component renders with title
        expect(screen.getByText('Paid subscription breakdown')).toBeInTheDocument();

        // Check that both cadence types are shown
        expect(screen.getByText('Monthly')).toBeInTheDocument();
        expect(screen.getByText('Annual')).toBeInTheDocument();

        // Total signups: monthly = 45 + 30 = 75, annual = 15 + 10 = 25, total = 100
        // Percentages: 75% and 25%
        expect(screen.getByText('75%')).toBeInTheDocument();
        expect(screen.getByText('25%')).toBeInTheDocument();
    });

    it('shows empty state with no signups in date range', () => {
        const mockEmptyData = {
            stats: [],
            meta: {
                totals: []
            }
        };

        mockSuccess(mockedUseSubscriptionStats, mockEmptyData);

        render(<NewSubscribersCadence isLoading={false} range={30} />);

        // Should show empty state with period-specific message
        expect(screen.getByText('No new subscribers')).toBeInTheDocument();
    });

    it('aggregates signups across all tiers for billing period breakdown', () => {
        const mockMultipleTiers = {
            tiers: [
                {id: 'tier-1', name: 'Premium', type: 'paid', active: true},
                {id: 'tier-2', name: 'Pro', type: 'paid', active: true}
            ]
        };

        mockSuccess(mockedUseBrowseTiers, mockMultipleTiers);

        const mockSubscriptionData = {
            stats: [
                {date: '2024-01-15', tier: 'tier-1', cadence: 'month', signups: 60, cancellations: 5, count: 100},
                {date: '2024-01-15', tier: 'tier-1', cadence: 'year', signups: 40, cancellations: 3, count: 50},
                {date: '2024-01-15', tier: 'tier-2', cadence: 'month', signups: 15, cancellations: 2, count: 30},
                {date: '2024-01-15', tier: 'tier-2', cadence: 'year', signups: 10, cancellations: 1, count: 20}
            ],
            meta: {
                totals: [
                    {tier: 'tier-1', cadence: 'month', count: 100},
                    {tier: 'tier-1', cadence: 'year', count: 50},
                    {tier: 'tier-2', cadence: 'month', count: 30},
                    {tier: 'tier-2', cadence: 'year', count: 20}
                ]
            }
        };

        mockSuccess(mockedUseSubscriptionStats, mockSubscriptionData);

        render(<NewSubscribersCadence isLoading={false} range={30} />);

        // Should aggregate signups: monthly = 60 + 15 = 75, annual = 40 + 10 = 50, total = 125
        // Percentages: 60% monthly, 40% annual
        expect(screen.getByText('Monthly')).toBeInTheDocument();
        expect(screen.getByText('Annual')).toBeInTheDocument();
        expect(screen.getByText('60%')).toBeInTheDocument();
        expect(screen.getByText('40%')).toBeInTheDocument();
    });

    it('hides breakdown type dropdown when only one tier is available', () => {
        // Single tier setup (from beforeEach default)
        const mockSubscriptionData = {
            stats: [
                {date: '2024-01-15', tier: 'tier-1', cadence: 'month', signups: 50, cancellations: 5, count: 100}
            ],
            meta: {
                totals: [
                    {tier: 'tier-1', cadence: 'month', count: 100}
                ]
            }
        };

        mockSuccess(mockedUseSubscriptionStats, mockSubscriptionData);

        render(<NewSubscribersCadence isLoading={false} range={30} />);

        // Should not show the dropdown when there's only one tier
        expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
    });

    it('shows breakdown type dropdown when multiple tiers are available', () => {
        const mockMultipleTiers = {
            tiers: [
                {id: 'tier-1', name: 'Premium', type: 'paid', active: true},
                {id: 'tier-2', name: 'Pro', type: 'paid', active: true}
            ]
        };

        mockSuccess(mockedUseBrowseTiers, mockMultipleTiers);

        const mockSubscriptionData = {
            stats: [
                {date: '2024-01-15', tier: 'tier-1', cadence: 'month', signups: 50, cancellations: 5, count: 100},
                {date: '2024-01-15', tier: 'tier-2', cadence: 'month', signups: 25, cancellations: 2, count: 50}
            ],
            meta: {
                totals: [
                    {tier: 'tier-1', cadence: 'month', count: 100},
                    {tier: 'tier-2', cadence: 'month', count: 50}
                ]
            }
        };

        mockSuccess(mockedUseSubscriptionStats, mockSubscriptionData);

        render(<NewSubscribersCadence isLoading={false} range={30} />);

        // Should show the dropdown when there are multiple tiers
        expect(screen.getByRole('combobox')).toBeInTheDocument();
    });
});
