export const DEFAULT_BANNER_POSITION = { x: 50, y: 50 };

export type BannerPosition = { x: number; y: number };

export type ParsedCampaignAttachment = {
    fileName: string;
    position: BannerPosition;
};

export type CampaignAttachmentInput = string | Record<string, unknown>;

const clampPosition = (value: number) => Math.min(100, Math.max(0, value));

const normalizePosition = (position?: Partial<BannerPosition> | null): BannerPosition => {
    const readAxis = (value: unknown, fallback: number) => {
        const num = Number(value);
        return Number.isFinite(num) ? clampPosition(num) : fallback;
    };

    return {
        x: readAxis(position?.x, DEFAULT_BANNER_POSITION.x),
        y: readAxis(position?.y, DEFAULT_BANNER_POSITION.y),
    };
};

const isPosition = (value: unknown): value is BannerPosition =>
    !!value &&
    typeof value === 'object' &&
    ('x' in value || 'y' in value);

export const parseCampaignAttachment = (item: CampaignAttachmentInput): ParsedCampaignAttachment => {
    if (typeof item === 'string') {
        const trimmed = item.trim();
        if (trimmed.startsWith('{')) {
            try {
                return parseCampaignAttachment(JSON.parse(trimmed) as CampaignAttachmentInput);
            } catch {
                // Fall back to plain filename string.
            }
        }
        return { fileName: item, position: { ...DEFAULT_BANNER_POSITION } };
    }

    if (item && typeof item === 'object') {
        const record = item as Record<string, unknown>;

        if (typeof record.fileName === 'string') {
            return {
                fileName: record.fileName,
                position: normalizePosition(record.position as BannerPosition),
            };
        }

        const fileName = Object.keys(record).find((key) => {
            if (key === 'position' || key === 'fileName') return false;
            const value = record[key];
            return typeof value === 'string' || isPosition(value);
        });

        if (fileName) {
            const value = record[fileName];
            if (isPosition(value)) {
                return { fileName, position: normalizePosition(value) };
            }

            if (record.position) {
                return {
                    fileName,
                    position: normalizePosition(record.position as BannerPosition),
                };
            }

            return { fileName, position: { ...DEFAULT_BANNER_POSITION } };
        }
    }

    return { fileName: '', position: { ...DEFAULT_BANNER_POSITION } };
};

/** `{ "banner.jpg": { "x": 35, "y": 60 } }` */
export const serializeCampaignAttachment = (fileName: string, position?: BannerPosition) => ({
    [fileName]: normalizePosition(position),
});

export const serializeCampaignAttachments = (
    files: Array<{ fileName: string; position?: BannerPosition }>,
) => files.map((file) => serializeCampaignAttachment(file.fileName, file.position));

export const getAttachmentKey = (attachments: CampaignAttachmentInput[] = []) =>
    attachments
        .map((item) => parseCampaignAttachment(item).fileName)
        .join('|');
