import { describe, expect, test } from "vitest";
import {
    measureProfileCardContent,
    mergeProfileCardLayoutMetadata,
    profileCardLayoutFromMetadata,
    profileCardMetadataJSON,
} from "./profileCardLayout.js";

describe("profile card layout detection", () => {
    test("ignores right-side grayscale mask when scanning video frames", () => {
        const width = 10;
        const height = 10;
        const frame = opaqueFrame(width, height, [0, 0, 0]);
        fillRect(frame.data, width, 7, 0, 3, height, [255, 255, 255, 255]);
        fillRect(frame.data, width, 1, 3, 5, 5, [255, 0, 0, 255]);

        const layout = measureProfileCardContent([frame]);

        expect(layout.color_content_width).toBeLessThan(width);
        expect(layout.content_top).toBe(3);
        expect(layout.content_bottom).toBe(7);
        expect(layout.content_height).toBe(5);
    });

    test("uses real alpha when the asset contains transparent rows", () => {
        const width = 12;
        const height = 12;
        const data = new Uint8ClampedArray(width * height * 4);
        fillRect(data, width, 0, 4, width, 7, [36, 120, 220, 255]);

        const layout = measureProfileCardContent([{ data, width, height }]);

        expect(layout.content_top).toBe(4);
        expect(layout.content_bottom).toBe(10);
        expect(layout.content_height).toBe(7);
    });

    test("ignores blank transparent frames instead of returning full height", () => {
        const width = 12;
        const height = 12;
        const blank = { data: new Uint8ClampedArray(width * height * 4), width, height };
        const content = { data: new Uint8ClampedArray(width * height * 4), width, height };
        fillRect(content.data, width, 0, 4, width, 7, [36, 120, 220, 255]);

        expect(measureProfileCardContent([blank, content]).content_top).toBe(4);
        expect(() => measureProfileCardContent([blank])).toThrow("资料卡素材没有解析到有效内容");
    });

    test("uses VAP alpha mask top instead of transient RGB decoration", () => {
        const width = 20;
        const height = 20;
        const alphaStarts = [5, 6, 7, 8];
        const frames = alphaStarts.map((alphaTop, index) => {
            const frame = opaqueFrame(width, height, [0, 0, 0]);
            fillRect(frame.data, width, 1, 2 + index, 3, 2, [255, 0, 0, 255]);
            fillRect(frame.data, width, 0, 8, 12, 10, [36, 120, 220, 255]);
            fillRect(frame.data, width, 12, alphaTop, 6, 10 - alphaTop, [255, 255, 255, 255]);
            return frame;
        });

        const layout = measureProfileCardContent(frames, {
            vapcLayout: {
                videoW: width,
                videoH: height,
                rgbFrame: [0, 0, 12, 18],
                aFrame: [12, 0, 6, 10],
            },
        });

        expect(layout.content_top).toBe(8);
        expect(layout.content_bottom).toBe(17);
        expect(layout.content_height).toBe(10);
        expect(layout.detect_version).toBe(2);
    });

    test("serializes only valid profile card layout metadata", () => {
        const metadataJson = mergeProfileCardLayoutMetadata("", {
            source_width: 10,
            source_height: 10,
            color_content_width: 7,
            content_top: 3,
            content_bottom: 7,
            content_height: 5,
            content_top_ratio: 0.3,
            content_height_ratio: 0.5,
            detect_version: 1,
        });

        expect(profileCardLayoutFromMetadata(metadataJson)).toMatchObject({
            content_top: 3,
            content_height: 5,
        });
        expect(profileCardMetadataJSON('{"unexpected":true}')).toBe("{}");
    });
});

function opaqueFrame(width, height, rgb) {
    const data = new Uint8ClampedArray(width * height * 4);
    fillRect(data, width, 0, 0, width, height, [rgb[0], rgb[1], rgb[2], 255]);
    return { data, width, height };
}

function fillRect(data, width, left, top, rectWidth, rectHeight, rgba) {
    for (let y = top; y < top + rectHeight; y += 1) {
        for (let x = left; x < left + rectWidth; x += 1) {
            const index = (y * width + x) * 4;
            data[index] = rgba[0];
            data[index + 1] = rgba[1];
            data[index + 2] = rgba[2];
            data[index + 3] = rgba[3];
        }
    }
}
