import React from 'react';
import { render } from '@testing-library/react';
import {
    TRANSFER_STATUS_VARIANT,
    TRANSFER_STATUS_FILLED,
    TRANSFER_STATUS_LABEL,
    formatPeriodKey,
} from '../transfer-list-table-columns';
import TransferListTableColumns from '../transfer-list-table-columns';
import type { ProjectTransferJob } from 'src/apollo/queries/transfer-projects';
import type {
    StatementPeriodInfo,
    VendorInfo,
} from '../transfer-list-table-columns';

jest.mock('src/components/shared/identity-name', () => ({
    __esModule: true,
    default: ({ identity }: { identity: string }) => (
        <span data-testid="identity-name">{identity}</span>
    ),
}));

jest.mock('src/components/account-detail/account-icon', () => ({
    __esModule: true,
    default: ({ brandName }: { brandName: string }) => (
        <span data-testid="account-icon">{brandName}</span>
    ),
}));

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    Link: ({ children, to }: { children: React.ReactNode; to: string }) => (
        <a href={to}>{children}</a>
    ),
}));

describe('TRANSFER_STATUS_VARIANT', () => {
    it('maps COMPLETED to success', () => {
        expect(TRANSFER_STATUS_VARIANT['COMPLETED']).toBe('success');
    });
    it('maps QUEUED (Pending) to orange', () => {
        expect(TRANSFER_STATUS_VARIANT['QUEUED']).toBe('warning');
    });
    it('maps PROCESSING to orange', () => {
        expect(TRANSFER_STATUS_VARIANT['PROCESSING']).toBe('warning');
    });
    it('maps FAILED to error', () => {
        expect(TRANSFER_STATUS_VARIANT['FAILED']).toBe('error');
    });
});

describe('TRANSFER_STATUS_FILLED', () => {
    it('uses a solid dot for QUEUED (Pending)', () => {
        expect(TRANSFER_STATUS_FILLED['QUEUED']).toBe(true);
    });
    it('uses a hollow circle for PROCESSING', () => {
        expect(TRANSFER_STATUS_FILLED['PROCESSING']).toBe(false);
    });
    it('uses a filled dot for COMPLETED', () => {
        expect(TRANSFER_STATUS_FILLED['COMPLETED']).toBe(true);
    });
});

describe('TRANSFER_STATUS_LABEL', () => {
    it('maps all four statuses to display labels', () => {
        expect(TRANSFER_STATUS_LABEL['COMPLETED']).toBe('Transferred');
        expect(TRANSFER_STATUS_LABEL['QUEUED']).toBe('Pending');
        expect(TRANSFER_STATUS_LABEL['PROCESSING']).toBe('Processing');
        expect(TRANSFER_STATUS_LABEL['FAILED']).toBe('Failed');
    });
});

describe('formatPeriodKey', () => {
    it('returns the next month after the cutoff date', () => {
        expect(formatPeriodKey('2026-02-01')).toBe('March 2026');
    });
    it('handles month rollover across years', () => {
        expect(formatPeriodKey('2025-12-01T00:00:00Z')).toBe('January 2026');
    });
});

const makeJob = (): ProjectTransferJob => ({
    projectTransferJobId: 'job-1',
    status: 'QUEUED',
    createdAt: '2024-01-01T00:00:00Z',
    transferCompletedOn: null,
    failureReason: null,
    projectCode: null,
    revenueCutoffDate: '2026-02-01',
    createdBy: { id: 'user@example.com' },
    originLabel: { vendorId: 10 },
    destinationLabel: { vendorId: 20 },
    project: { projectId: 1, projectName: 'My Project' },
    products: [],
});

const emptyPeriods = new Map<string, StatementPeriodInfo>();
const emptySubaccounts = new Map<string, string>();
const noOp = () => {};

describe('TransferListTableColumns vendor name resolution', () => {
    const vendorNames = new Map<number, VendorInfo>([
        [
            10,
            {
                name: 'Orchard US',
                accountId: 'acct-10',
                brandName: 'theorchard',
            },
        ],
        [20, { name: 'Orchard UK', accountId: 'acct-20' }],
    ]);

    it('renders origin account name from the vendor map', () => {
        const cols = TransferListTableColumns(
            vendorNames,
            emptySubaccounts,
            emptyPeriods,
            noOp
        );
        const col = cols.find(c => c.name === 'originLabel')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByText } = render(<Cell data={makeJob()} />);
        expect(getByText('Orchard US')).toBeInTheDocument();
    });

    it('renders origin account name as a link to the account page', () => {
        const cols = TransferListTableColumns(
            vendorNames,
            emptySubaccounts,
            emptyPeriods,
            noOp
        );
        const col = cols.find(c => c.name === 'originLabel')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByRole } = render(<Cell data={makeJob()} />);
        expect(getByRole('link')).toHaveAttribute('href', '/account/acct-10');
    });

    it('renders origin vendor ID as a labeled subtext', () => {
        const cols = TransferListTableColumns(
            vendorNames,
            emptySubaccounts,
            emptyPeriods,
            noOp
        );
        const col = cols.find(c => c.name === 'originLabel')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByText } = render(<Cell data={makeJob()} />);
        expect(getByText('ID: 10')).toBeInTheDocument();
    });

    it('renders a labeled Subaccount ID line when present', () => {
        const job: ProjectTransferJob = {
            ...makeJob(),
            originLabel: { vendorId: 10, subaccountId: 99 },
        };
        const cols = TransferListTableColumns(
            vendorNames,
            new Map([['10:99', 'Sub Label']]),
            emptyPeriods,
            noOp
        );
        const col = cols.find(c => c.name === 'originLabel')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByText } = render(<Cell data={job} />);
        expect(getByText('ID: 10')).toBeInTheDocument();
        expect(getByText('Subaccount ID: 99')).toBeInTheDocument();
        expect(getByText('Sub Label')).toBeInTheDocument();
    });

    it('renders destination account name from the vendor map', () => {
        const cols = TransferListTableColumns(
            vendorNames,
            emptySubaccounts,
            emptyPeriods,
            noOp
        );
        const col = cols.find(c => c.name === 'destinationLabel')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByText } = render(<Cell data={makeJob()} />);
        expect(getByText('Orchard UK')).toBeInTheDocument();
    });

    it('falls back to the raw vendor ID when not in the map', () => {
        const empty = new Map<number, VendorInfo>();
        const cols = TransferListTableColumns(
            empty,
            emptySubaccounts,
            emptyPeriods,
            noOp
        );
        const col = cols.find(c => c.name === 'originLabel')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getAllByText } = render(<Cell data={makeJob()} />);
        expect(getAllByText('10').length).toBeGreaterThan(0);
    });
});

describe('TransferListTableColumns affected statement period', () => {
    const vendorNames = new Map<number, VendorInfo>();
    const periods = new Map<string, StatementPeriodInfo>([
        [
            'March 2026',
            { statementPeriodId: '326', statementPeriodName: 'March 2026' },
        ],
    ]);

    it('renders the period name derived from revenueCutoffDate', () => {
        const cols = TransferListTableColumns(
            vendorNames,
            emptySubaccounts,
            periods,
            noOp
        );
        const col = cols.find(c => c.name === 'revenueCutoffDate')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByText } = render(<Cell data={makeJob()} />);
        expect(getByText('March 2026')).toBeInTheDocument();
    });

    it('renders the statement period ID as subtext when found', () => {
        const cols = TransferListTableColumns(
            vendorNames,
            emptySubaccounts,
            periods,
            noOp
        );
        const col = cols.find(c => c.name === 'revenueCutoffDate')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByText } = render(<Cell data={makeJob()} />);
        expect(getByText('326')).toBeInTheDocument();
    });

    it('renders nothing when revenueCutoffDate is null', () => {
        const job = { ...makeJob(), revenueCutoffDate: null };
        const cols = TransferListTableColumns(
            vendorNames,
            emptySubaccounts,
            periods,
            noOp
        );
        const col = cols.find(c => c.name === 'revenueCutoffDate')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { container } = render(<Cell data={job} />);
        expect(container.textContent).toBe('');
    });
});

describe('TransferListTableColumns created by', () => {
    it('renders IdentityName with the createdBy id', () => {
        const cols = TransferListTableColumns(
            new Map(),
            emptySubaccounts,
            emptyPeriods,
            noOp
        );
        const col = cols.find(c => c.name === 'createdBy')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByTestId } = render(<Cell data={makeJob()} />);
        expect(getByTestId('identity-name').textContent).toBe(
            'user@example.com'
        );
    });
});

describe('TransferListTableColumns delete action', () => {
    it('calls onDelete with the job ID when the trash button is clicked', () => {
        const onDelete = jest.fn();
        const cols = TransferListTableColumns(
            new Map(),
            emptySubaccounts,
            emptyPeriods,
            onDelete
        );
        const col = cols.find(c => c.name === 'actions')!;
        const Cell = col.Cell as React.FC<{ data: ProjectTransferJob }>;
        const { getByRole } = render(<Cell data={makeJob()} />);
        getByRole('button').click();
        expect(onDelete).toHaveBeenCalledWith('job-1');
    });
});
