import { Notes, Memoriets } from "../../../../models/index.js";
import { MAX_NOTE_TEXT_LENGTH } from "../../../../const.js";
import { noteVisibilities } from "../../../../types.js";
import { ApiError } from "../../error.js";
import define from "../../define.js";
import { HOUR } from "../../../../const.js";
import { createNoteFromApiData } from "../../../../services/note/create-from-api.js";
import { genId } from "../../../../misc/gen-id.js";
export const meta = {
    tags: [
        "memoriet"
    ],
    requireCredential: true,
    limit: {
        duration: HOUR,
        max: 300
    },
    kind: "write:notes",
    res: {
        type: "object",
        optional: false,
        nullable: false,
        properties: {
            memoriet: {
                type: "object",
                optional: false,
                nullable: false,
                properties: {
                    id: {
                        type: "string",
                        optional: false,
                        nullable: false
                    },
                    expiresAt: {
                        type: "string",
                        optional: false,
                        nullable: true
                    },
                    textLayers: {
                        type: "array",
                        optional: false,
                        nullable: false,
                        items: {
                            type: "object",
                            optional: false,
                            nullable: false
                        }
                    },
                    note: {
                        type: "object",
                        optional: false,
                        nullable: false,
                        ref: "Note"
                    }
                }
            }
        }
    },
    errors: {
        cannotExpireToPast: {
            message: "Expiration time must be in the future.",
            code: "CANNOT_EXPIRE_TO_PAST",
            id: "4b86af67-c80f-46ef-a166-440c4e3cf83a"
        }
    }
};
export const paramDef = {
    type: "object",
    properties: {
        visibility: {
            type: "string",
            enum: noteVisibilities,
            default: "home"
        },
        visibleUserIds: {
            type: "array",
            uniqueItems: true,
            items: {
                type: "string",
                format: "misskey:id"
            }
        },
        text: {
            type: "string",
            maxLength: MAX_NOTE_TEXT_LENGTH,
            nullable: true
        },
        cw: {
            type: "string",
            nullable: true,
            maxLength: 100
        },
        fileIds: {
            type: "array",
            uniqueItems: true,
            minItems: 1,
            maxItems: 16,
            items: {
                type: "string",
                format: "misskey:id"
            }
        },
        textLayers: {
            type: "array",
            maxItems: 32,
            default: [],
            items: {
                type: "object",
                properties: {
                    id: {
                        type: "string",
                        maxLength: 64
                    },
                    text: {
                        type: "string",
                        minLength: 1,
                        maxLength: 200
                    },
                    color: {
                        type: "string",
                        maxLength: 32
                    },
                    backgroundColor: {
                        type: "string",
                        maxLength: 32,
                        nullable: true
                    },
                    backgroundWidth: {
                        type: "number",
                        minimum: 0,
                        maximum: 100,
                        nullable: true
                    },
                    backgroundHeight: {
                        type: "number",
                        minimum: 0,
                        maximum: 100,
                        nullable: true
                    },
                    fontSize: {
                        type: "number",
                        minimum: 8,
                        maximum: 96
                    },
                    x: {
                        type: "number",
                        minimum: 0,
                        maximum: 100
                    },
                    y: {
                        type: "number",
                        minimum: 0,
                        maximum: 100
                    },
                    rotate: {
                        type: "number",
                        minimum: -180,
                        maximum: 180
                    }
                },
                required: [
                    "text"
                ],
                additionalProperties: false
            }
        },
        expiresAt: {
            type: "integer",
            nullable: true
        }
    },
    anyOf: [
        {
            properties: {
                text: {
                    type: "string",
                    minLength: 1,
                    maxLength: MAX_NOTE_TEXT_LENGTH,
                    nullable: false
                }
            },
            required: [
                "text"
            ]
        },
        {
            required: [
                "fileIds"
            ]
        }
    ]
};
const colorPattern = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
function clamp(value, min, max, fallback) {
    const num = typeof value === "number" && Number.isFinite(value) ? value : fallback;
    return Math.min(max, Math.max(min, num));
}
function normalizeColor(value, fallback) {
    return typeof value === "string" && colorPattern.test(value) ? value : fallback;
}
function normalizeTextLayers(layers) {
    if (!Array.isArray(layers)) return [];
    return layers.slice(0, 32).flatMap((layer, index)=>{
        if (layer == null || typeof layer !== "object") return [];
        const input = layer;
        const text = typeof input.text === "string" ? input.text.trim().slice(0, 200) : "";
        if (text.length === 0) return [];
        const backgroundColor = input.backgroundColor == null || input.backgroundColor === "transparent" ? null : normalizeColor(input.backgroundColor, "#000000cc");
        return [
            {
                id: typeof input.id === "string" && input.id.length > 0 ? input.id.slice(0, 64) : genId(),
                text,
                color: normalizeColor(input.color, "#ffffff"),
                backgroundColor,
                backgroundWidth: input.backgroundWidth == null ? null : clamp(input.backgroundWidth, 0, 100, 0),
                backgroundHeight: input.backgroundHeight == null ? null : clamp(input.backgroundHeight, 0, 100, 0),
                fontSize: clamp(input.fontSize, 8, 96, 28),
                x: clamp(input.x, 0, 100, 50),
                y: clamp(input.y, 0, 100, 50 + index * 6),
                rotate: clamp(input.rotate, -180, 180, 0)
            }
        ];
    });
}
export default define(meta, paramDef, async (ps, user)=>{
    const expiresAt = typeof ps.expiresAt === "number" ? new Date(ps.expiresAt) : null;
    if (expiresAt != null && expiresAt.getTime() <= Date.now()) {
        throw new ApiError(meta.errors.cannotExpireToPast);
    }
    const textLayers = normalizeTextLayers(ps.textLayers);
    const note = await createNoteFromApiData(user, {
        text: ps.text ? `${ps.text.trim()}\n#Memoriet` : "#Memoriet",
        cw: ps.cw,
        fileIds: ps.fileIds,
        visibility: ps.visibility,
        visibleUserIds: ps.visibleUserIds,
        localOnly: true
    }, new Date());
    const memoriet = await Memoriets.save({
        id: genId(),
        createdAt: new Date(),
        userId: user.id,
        noteId: note.id,
        expiresAt,
        textLayers
    });
    return {
        memoriet: {
            id: memoriet.id,
            expiresAt: memoriet.expiresAt?.toISOString() ?? null,
            textLayers: memoriet.textLayers,
            note: await Notes.pack(note, user)
        }
    };
});
