import React, { useState } from 'react';
import { Slot } from 'radix-ui';
import { Dialog, Text, Badge } from '@preply/ds-web-lib';
import styled from 'styled-components';
import { getTokenVar as t } from '@preply/ds-web-core';
import { spacing, color, radius } from '@preply/ds-core';

type FontFamily = 'Platform' | 'Figtree' | 'Noto Sans';

const FONT_FAMILY_FULL: Record<FontFamily, string> = {
    Platform:
        "'Platform', 'Platform-fallback', 'Platform-fallback-android', 'Noto Sans', 'NotoSans-fallback', 'NotoSans-fallback-android', sans-serif",
    Figtree:
        "'Figtree', 'Figtree-fallback', 'Figtree-fallback-android', 'Noto Sans', 'NotoSans-fallback', 'NotoSans-fallback-android', sans-serif",
    'Noto Sans': "'Noto Sans', 'NotoSans-fallback', 'NotoSans-fallback-android', sans-serif",
};

type UnicodeRange = {
    name: string;
    start: number;
    end: number;
};

const UNICODE_RANGES: UnicodeRange[] = [
    { name: 'Basic Latin', start: 0x0020, end: 0x007f },
    { name: 'Latin-1 Supplement', start: 0x00a0, end: 0x00ff },
    { name: 'Latin Extended-A', start: 0x0100, end: 0x017f },
    { name: 'Latin Extended-B', start: 0x0180, end: 0x024f },
    { name: 'Spacing Modifier Letters', start: 0x02b0, end: 0x02ff },
    { name: 'Cyrillic', start: 0x0400, end: 0x04ff },
    { name: 'Arabic', start: 0x0600, end: 0x06ff },
    { name: 'Thai', start: 0x0e00, end: 0x0e7f },
    { name: 'Latin Extended Additional', start: 0x1e00, end: 0x1eff },
    { name: 'General Punctuation', start: 0x2000, end: 0x206f },
    { name: 'Currency Symbols', start: 0x20a0, end: 0x20cf },
];

function generateCharacters(range: UnicodeRange): { char: string; codePoint: number }[] {
    const characters: { char: string; codePoint: number }[] = [];

    for (let codePoint = range.start; codePoint <= range.end; codePoint++) {
        const char = String.fromCodePoint(codePoint);
        // Skip control characters and non-printable characters
        if (codePoint < 0x0020 || (codePoint >= 0x007f && codePoint < 0x00a0)) {
            continue;
        }
        characters.push({ char, codePoint });
    }

    return characters;
}

function formatCodePoint(codePoint: number): string {
    return `U+${codePoint.toString(16).toUpperCase().padStart(4, '0')}`;
}

const ranges = UNICODE_RANGES.map(range => ({
    ...range,
    characters: generateCharacters(range),
}));

const Container = styled.div`
    display: flex;
    flex-direction: column;
    gap: ${t(spacing[24])};
    max-height: 60vh;
    overflow-y: auto;
`;

const RangeSection = styled.div`
    display: flex;
    flex-direction: column;
    gap: ${t(spacing[8])};
`;

const RangeHeader = styled.div`
    display: flex;
    align-items: center;
    gap: ${t(spacing[8])};
    position: sticky;
    top: 0;
    background: ${t(color.background.primary)};
    padding: ${t(spacing[8])} 0;
`;

const CharacterGrid = styled.div`
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
    gap: ${t(spacing[4])};
`;

const CharacterCell = styled.div<{ $fontFamily: string }>`
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: ${t(spacing[4])};
    padding: ${t(spacing[8])};
    border: 1px solid ${t(color.border.tertiary)};
    border-radius: ${t(radius[4])};
`;

const Character = styled.span<{ $fontFamily: string }>`
    font-family: ${props => FONT_FAMILY_FULL[props.$fontFamily]} !important;
    font-size: 20px;
    min-height: 24px;
`;

const CodePoint = styled.span`
    font-size: 9px;
    color: ${t(color.text.tertiary)};
    font-family: monospace;
`;

type Props = {
    fontFamily: FontFamily;
    children: React.ReactNode;
};

export function UnicodeTableDialog({ fontFamily, children }: Props) {
    const [open, setOpen] = useState(false);

    return (
        <>
            <Slot.Root onClick={() => setOpen(true)}>{children}</Slot.Root>
            <Dialog
                open={open}
                onClose={() => setOpen(false)}
                title={`Unicode Table - ${fontFamily}`}
                description=""
                size="lg"
            >
                <Container>
                    {ranges.map(range => (
                        <RangeSection key={range.name}>
                            <RangeHeader>
                                <Text variant="default-semibold">{range.name}</Text>
                                <Badge size="small">
                                    {formatCodePoint(range.start)} – {formatCodePoint(range.end)}
                                </Badge>
                            </RangeHeader>
                            <CharacterGrid>
                                {range.characters.map(({ char, codePoint }) => (
                                    <CharacterCell
                                        key={codePoint}
                                        $fontFamily={fontFamily}
                                        title={`${char} — ${formatCodePoint(codePoint)}`}
                                    >
                                        <Character $fontFamily={fontFamily}>{char}</Character>
                                        <CodePoint>{formatCodePoint(codePoint)}</CodePoint>
                                    </CharacterCell>
                                ))}
                            </CharacterGrid>
                        </RangeSection>
                    ))}
                </Container>
            </Dialog>
        </>
    );
}
