import type { ComponentType } from 'react';
import {
    Heading as HeadingIcon,
    Image as ImageIcon,
    MinusSquare,
    MousePointerClick,
    Pilcrow,
    Tag,
    Type,
} from 'lucide-react';

import type {
    AtomicBlock,
    ButtonBlock,
    EyebrowBlock,
    HeadingBlock,
    ImageBlock,
    SpacerBlock,
    SubheadBlock,
    TextBlock,
} from './cms-types';

import ButtonBlockRenderer from './atomic-blocks/ButtonBlock';
import EyebrowBlockRenderer from './atomic-blocks/EyebrowBlock';
import HeadingBlockRenderer from './atomic-blocks/HeadingBlock';
import ImageBlockRenderer from './atomic-blocks/ImageBlock';
import SpacerBlockRenderer from './atomic-blocks/SpacerBlock';
import SubheadBlockRenderer from './atomic-blocks/SubheadBlock';
import TextBlockRenderer from './atomic-blocks/TextBlock';

import ButtonEditor from '@/admin/marketing/atomic-blocks/ButtonEditor';
import EyebrowEditor from '@/admin/marketing/atomic-blocks/EyebrowEditor';
import HeadingEditor from '@/admin/marketing/atomic-blocks/HeadingEditor';
import ImageEditor from '@/admin/marketing/atomic-blocks/ImageEditor';
import { newBlockId } from '@/admin/marketing/atomic-blocks/shared';
import SpacerEditor from '@/admin/marketing/atomic-blocks/SpacerEditor';
import SubheadEditor from '@/admin/marketing/atomic-blocks/SubheadEditor';
import TextEditor from '@/admin/marketing/atomic-blocks/TextEditor';

export type AtomicBlockMeta<TBlock extends AtomicBlock = AtomicBlock> = {
    type: TBlock['type'];
    label: string;
    description: string;
    icon: ComponentType<{ className?: string }>;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    renderer: ComponentType<{ block: any }>;
    editor: ComponentType<{
        value: TBlock;
        onChange: (next: TBlock) => void;
        errors?: Record<string, string>;
    }>;
    defaultData: () => TBlock;
};

type AtomicRegistryShape = {
    [K in AtomicBlock['type']]: AtomicBlockMeta<Extract<AtomicBlock, { type: K }>>;
};

export const ATOMIC_BLOCK_REGISTRY: AtomicRegistryShape = {
    heading: {
        type: 'heading',
        label: 'Heading',
        description: 'Section title with optional accent',
        icon: HeadingIcon,
        renderer: HeadingBlockRenderer,
        editor: HeadingEditor,
        defaultData: (): HeadingBlock => ({
            id: newBlockId('heading'),
            type: 'heading',
            html: '<p>New heading</p>',
            size: 'h2',
            align: 'left',
        }),
    },
    subhead: {
        type: 'subhead',
        label: 'Subhead',
        description: 'Lead paragraph',
        icon: Pilcrow,
        renderer: SubheadBlockRenderer,
        editor: SubheadEditor,
        defaultData: (): SubheadBlock => ({
            id: newBlockId('subhead'),
            type: 'subhead',
            html: '<p>Lead paragraph</p>',
            align: 'left',
        }),
    },
    eyebrow: {
        type: 'eyebrow',
        label: 'Eyebrow',
        description: 'Small uppercase pill',
        icon: Tag,
        renderer: EyebrowBlockRenderer,
        editor: EyebrowEditor,
        defaultData: (): EyebrowBlock => ({
            id: newBlockId('eyebrow'),
            type: 'eyebrow',
            text: 'Eyebrow',
            align: 'left',
        }),
    },
    text: {
        type: 'text',
        label: 'Text',
        description: 'Body copy with rich formatting',
        icon: Type,
        renderer: TextBlockRenderer,
        editor: TextEditor,
        defaultData: (): TextBlock => ({
            id: newBlockId('text'),
            type: 'text',
            html: '<p>Body text</p>',
        }),
    },
    button: {
        type: 'button',
        label: 'Button',
        description: 'Primary or secondary action',
        icon: MousePointerClick,
        renderer: ButtonBlockRenderer,
        editor: ButtonEditor,
        defaultData: (): ButtonBlock => ({
            id: newBlockId('button'),
            type: 'button',
            label: 'Get started',
            href: '/',
            variant: 'primary',
            align: 'left',
        }),
    },
    image: {
        type: 'image',
        label: 'Image',
        description: 'Uploaded image',
        icon: ImageIcon,
        renderer: ImageBlockRenderer,
        editor: ImageEditor,
        defaultData: (): ImageBlock => ({
            id: newBlockId('image'),
            type: 'image',
            image: '',
            align: 'left',
        }),
    },
    spacer: {
        type: 'spacer',
        label: 'Spacer',
        description: 'Vertical whitespace',
        icon: MinusSquare,
        renderer: SpacerBlockRenderer,
        editor: SpacerEditor,
        defaultData: (): SpacerBlock => ({
            id: newBlockId('spacer'),
            type: 'spacer',
            size: 'md',
        }),
    },
};

// Display order in the admin "Add block" menu inside Custom sections.
// New atomic types append here.
export const ATOMIC_BLOCK_PICK_ORDER: AtomicBlock['type'][] = [
    'heading',
    'subhead',
    'eyebrow',
    'text',
    'button',
    'image',
    'spacer',
];

/** Lookup helper. Returns null for unknown discriminators so the renderer +
 *  editor dispatchers can fall through gracefully (mirrors how
 *  `getBlockMeta` works for sections). Saved payloads referencing
 *  retired block types render as nothing rather than crashing. */
export function getAtomicBlockMeta(type: string): AtomicBlockMeta | null {
    return (ATOMIC_BLOCK_REGISTRY as unknown as Record<string, AtomicBlockMeta>)[type] ?? null;
}
