import React from 'react';
import SourceIcon from '../../components/source-icon';
import {BaseSourceData, ProcessedSourceData, extendSourcesWithPercentages, processSources} from '@tryghost/admin-x-framework';
import {Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DataList, DataListBar, DataListBody, DataListHead, DataListHeader, DataListItemContent, DataListItemValue, DataListItemValueAbs, DataListItemValuePerc, DataListRow, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger, SkeletonTable} from '@tryghost/shade/components';
import {HTable} from '@tryghost/shade/primitives';
import {LucideIcon, formatNumber, formatPercentage} from '@tryghost/shade/utils';
import {getPeriodText} from '@src/utils/chart-helpers';
import {useGlobalData} from '@src/providers/post-analytics-context';

// Default source icon URL - apps can override this
const DEFAULT_SOURCE_ICON_URL = 'https://www.google.com/s2/favicons?domain=ghost.org&sz=64';

interface SourcesTableProps {
    data: ProcessedSourceData[] | null;
    range?: number;
    defaultSourceIconUrl?: string;
    dataTableHeader: boolean;
    onSourceClick?: (source: string) => void;
}

export const SourcesTable: React.FC<SourcesTableProps> = ({dataTableHeader, data, defaultSourceIconUrl = DEFAULT_SOURCE_ICON_URL, onSourceClick}) => {
    return (
        <DataList>
            {dataTableHeader &&
                <DataListHeader>
                    <DataListHead>Source</DataListHead>
                    <DataListHead>Visitors</DataListHead>
                </DataListHeader>
            }
            <DataListBody>
                {data?.map((row) => {
                    const isClickable = !!onSourceClick;
                    const sourceId = row.source ? row.source.toLowerCase().replace(/[^a-z0-9]/g, '-') : 'direct';
                    return (
                        <DataListRow
                            key={row.source}
                            className={`group/row ${isClickable ? 'cursor-pointer' : ''}`}
                            data-testid={`source-row-${sourceId}`}
                            onClick={isClickable ? () => onSourceClick(row.source) : undefined}
                        >
                            <DataListBar style={{
                                width: `${row.percentage ? Math.round(row.percentage * 100) : 0}%`
                            }} />
                            <DataListItemContent className='group-hover/datalist:max-w-[calc(100%-140px)]'>
                                <div className='flex items-center space-x-4 overflow-hidden'>
                                    <div className='truncate font-medium'>
                                        {row.linkUrl && !onSourceClick ?
                                            <a className='group/link flex items-center gap-2' href={row.linkUrl} rel="noreferrer" target="_blank">
                                                <SourceIcon
                                                    defaultSourceIconUrl={defaultSourceIconUrl}
                                                    displayName={row.displayName}
                                                    iconSrc={row.iconSrc}
                                                />
                                                <span className='group-hover/link:underline'>{row.displayName}</span>
                                            </a>
                                            :
                                            <span className='flex items-center gap-2'>
                                                <SourceIcon
                                                    defaultSourceIconUrl={defaultSourceIconUrl}
                                                    displayName={row.displayName}
                                                    iconSrc={row.iconSrc}
                                                />
                                                <span>{row.displayName}</span>
                                            </span>
                                        }
                                    </div>
                                </div>
                            </DataListItemContent>
                            <DataListItemValue>
                                <DataListItemValueAbs>{formatNumber(row.visits)}</DataListItemValueAbs>
                                <DataListItemValuePerc>{formatPercentage(row.percentage || 0)}</DataListItemValuePerc>
                            </DataListItemValue>
                        </DataListRow>
                    );
                })}
            </DataListBody>
        </DataList>
    );
};

interface SourcesCardProps {
    title?: string;
    description?: string;
    data: BaseSourceData[] | null;
    range?: number;
    totalVisitors?: number;
    siteUrl?: string;
    siteIcon?: string;
    defaultSourceIconUrl?: string;
    getPeriodText?: (range: number) => string;
    tableOnly?: boolean;
    topSourcesLimit?:number;
    onSourceClick?: (source: string) => void;
}

export const Sources: React.FC<SourcesCardProps> = ({
    data,
    range = 30,
    totalVisitors = 0,
    siteUrl,
    siteIcon,
    defaultSourceIconUrl = DEFAULT_SOURCE_ICON_URL,
    tableOnly = false,
    topSourcesLimit = 10,
    onSourceClick
}) => {
    const {isPostLoading} = useGlobalData();

    // Process and group sources data with pre-computed icons and display values
    const processedData = React.useMemo(() => {
        return processSources({
            data,
            mode: 'visits',
            siteUrl,
            siteIcon,
            defaultSourceIconUrl
        });
    }, [data, siteUrl, siteIcon, defaultSourceIconUrl]);

    // Extend processed data with percentage values for visits mode
    const extendedData = React.useMemo(() => {
        return extendSourcesWithPercentages({
            processedData,
            totalVisitors,
            mode: 'visits'
        });
    }, [processedData, totalVisitors]);

    const topSources = extendedData.slice(0, topSourcesLimit);

    // Generate title and description based on mode and range
    const cardTitle = 'Top sources';
    const cardDescription = `How readers found this post ${range && ` ${getPeriodText(range)}`}`;

    if (tableOnly) {
        const limitedData = extendedData.slice(0, topSourcesLimit);
        const hasMore = extendedData.length > topSourcesLimit;

        return (
            <div>
                <SourcesTable
                    data={limitedData}
                    dataTableHeader={false}
                    defaultSourceIconUrl={defaultSourceIconUrl}
                    range={range}
                    onSourceClick={onSourceClick}
                />
                {hasMore && (
                    <div className='mt-4'>
                        <Sheet>
                            <SheetTrigger asChild>
                                <Button className='w-full' size='sm' variant='outline'>
                                    View all ({extendedData.length}) <LucideIcon.ArrowRight size={14} />
                                </Button>
                            </SheetTrigger>
                            <SheetContent className='overflow-y-auto pt-0 sm:max-w-[600px]'>
                                <SheetHeader className='sticky top-0 z-40 -mx-6 bg-background/60 p-6 backdrop-blur'>
                                    <SheetTitle>{cardTitle}</SheetTitle>
                                    <SheetDescription>{cardDescription}</SheetDescription>
                                </SheetHeader>
                                <div className='group/datalist'>
                                    <SourcesTable
                                        data={extendedData}
                                        dataTableHeader={true}
                                        defaultSourceIconUrl={defaultSourceIconUrl}
                                        range={range}
                                        onSourceClick={onSourceClick}
                                    />
                                </div>
                            </SheetContent>
                        </Sheet>
                    </div>
                )}
            </div>
        );
    }

    const isLoading = isPostLoading;

    return (
        <Card className='group/datalist' data-testid="top-sources-card">
            <div className='flex items-center justify-between p-6'>
                <CardHeader className='p-0'>
                    <CardTitle>{cardTitle}</CardTitle>
                    <CardDescription>{cardDescription}</CardDescription>
                </CardHeader>
                <HTable className='mr-2'>Visitors</HTable>
            </div>
            <CardContent className='overflow-hidden'>
                <div className='h-[1px] w-full bg-border' />
                {isLoading ?
                    <SkeletonTable lines={5} />
                    :
                    (topSources.length > 0 ? (
                        <SourcesTable
                            data={topSources}
                            dataTableHeader={false}
                            defaultSourceIconUrl={defaultSourceIconUrl}
                            range={range}
                            onSourceClick={onSourceClick}
                        />
                    ) : (
                        <div className='py-20 text-center text-sm text-gray-700'>
                    No sources data available.
                        </div>
                    ))
                }
            </CardContent>
            {extendedData.length > 10 &&
                <CardFooter>
                    <Sheet>
                        <SheetTrigger asChild>
                            <Button variant='outline'>View all <LucideIcon.TableOfContents /></Button>
                        </SheetTrigger>
                        <SheetContent className='overflow-y-auto pt-0 sm:max-w-[600px]'>
                            <SheetHeader className='sticky top-0 z-40 -mx-6 bg-background/60 p-6 backdrop-blur'>
                                <SheetTitle>{cardTitle}</SheetTitle>
                                <SheetDescription>{cardDescription}</SheetDescription>
                            </SheetHeader>
                            <div className='group/datalist'>
                                <SourcesTable
                                    data={extendedData}
                                    dataTableHeader={true}
                                    defaultSourceIconUrl={defaultSourceIconUrl}
                                    range={range}
                                    onSourceClick={onSourceClick}
                                />
                            </div>
                        </SheetContent>
                    </Sheet>
                </CardFooter>
            }
        </Card>
    );
};

export default Sources;
