/**
 * 文件功能：聊天室歼-35 战机入场特效
 *
 * 使用全屏透明 Canvas 绘制隐身战机高速掠过、喷口尾焰、音爆环、
 * 流光航迹与战术 HUD 字幕，作为座驾/载具入场的战机版本原型。
 */

const J35Effect = (() => {
    const DURATION = 8200;
    const STEEL = "#9ca3af";
    const DARK_STEEL = "#1f2937";
    const COCKPIT = "#0f172a";
    const AFTERBURNER = "#38bdf8";
    const WARNING_RED = "#ef4444";

    /**
     * 缓出曲线，用于战机高速进场后略微减速展示。
     *
     * @param {number} t 0 到 1 的进度
     * @returns {number}
     */
    function easeOutCubic(t) {
        return 1 - Math.pow(1 - t, 3);
    }

    /**
     * 缓入缓出曲线，用于 HUD 与音爆环淡入淡出。
     *
     * @param {number} t 0 到 1 的进度
     * @returns {number}
     */
    function easeInOutSine(t) {
        return -(Math.cos(Math.PI * t) - 1) / 2;
    }

    /**
     * 创建高速流光粒子。
     *
     * @param {number} w 画布宽度
     * @param {number} h 画布高度
     * @returns {Array<Record<string, number|string>>}
     */
    function createSpeedLines(w, h) {
        return Array.from({ length: 110 }, () => ({
            x: Math.random() * w,
            y: h * (0.18 + Math.random() * 0.68),
            speed: 2 + Math.random() * 5,
            length: 90 + Math.random() * 190,
            alpha: 0.18 + Math.random() * 0.42,
            color: [AFTERBURNER, "#ffffff", "#fde68a", "#60a5fa"][Math.floor(Math.random() * 4)],
        }));
    }

    /**
     * 绘制夜航背景与扫描网格。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} w 画布宽度
     * @param {number} h 画布高度
     * @param {number} progress 播放进度
     */
    function drawBackdrop(ctx, w, h, progress) {
        const fade = Math.min(1, progress / 0.16) * Math.min(1, (1 - progress) / 0.12);
        const gradient = ctx.createRadialGradient(w * 0.5, h * 0.48, 0, w * 0.5, h * 0.5, Math.max(w, h) * 0.82);
        gradient.addColorStop(0, `rgba(15,23,42,${0.52 * fade})`);
        gradient.addColorStop(0.55, `rgba(8,47,73,${0.26 * fade})`);
        gradient.addColorStop(1, "rgba(0,0,0,0)");

        ctx.save();
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, w, h);
        ctx.globalCompositeOperation = "lighter";

        for (let i = 0; i < 10; i++) {
            const y = h * (0.18 + i * 0.07);
            ctx.strokeStyle = `rgba(56,189,248,${0.08 * fade})`;
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(0, y + Math.sin(progress * 18 + i) * 6);
            ctx.lineTo(w, y + Math.cos(progress * 15 + i) * 6);
            ctx.stroke();
        }

        ctx.restore();
    }

    /**
     * 绘制高速运动线，方向与战机飞行一致。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {Array<Record<string, number|string>>} lines 流光线集合
     * @param {number} w 画布宽度
     * @param {number} progress 播放进度
     */
    function drawSpeedLines(ctx, lines, w, progress) {
        const fade = Math.min(1, progress / 0.12) * Math.min(1, (1 - progress) / 0.1);

        ctx.save();
        ctx.globalCompositeOperation = "lighter";
        lines.forEach((line, index) => {
            const travel = (progress * (900 + line.speed * 120) + index * 71) % (w + 520);
            const x = w + 260 - travel;
            ctx.globalAlpha = line.alpha * fade;
            ctx.strokeStyle = line.color;
            ctx.lineWidth = 1.4 + line.speed * 0.18;
            ctx.shadowColor = line.color;
            ctx.shadowBlur = 12;
            ctx.beginPath();
            ctx.moveTo(x, line.y);
            ctx.lineTo(x + line.length, line.y + Math.sin(progress * 22 + index) * 4);
            ctx.stroke();
        });
        ctx.restore();
    }

    /**
     * 绘制战机尾部双发喷口尾焰。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} progress 播放进度
     */
    function drawAfterburners(ctx, progress) {
        const pulse = 0.78 + Math.sin(progress * 70) * 0.16;

        ctx.save();
        ctx.globalCompositeOperation = "lighter";
        [[168, -12], [168, 12]].forEach(([x, y]) => {
            const flame = ctx.createLinearGradient(x, y, x + 170, y);
            flame.addColorStop(0, `rgba(255,255,255,${0.9 * pulse})`);
            flame.addColorStop(0.18, `rgba(56,189,248,${0.78 * pulse})`);
            flame.addColorStop(0.58, `rgba(59,130,246,${0.3 * pulse})`);
            flame.addColorStop(1, "rgba(59,130,246,0)");
            ctx.fillStyle = flame;
            ctx.shadowColor = AFTERBURNER;
            ctx.shadowBlur = 26;
            ctx.beginPath();
            ctx.moveTo(x, y - 9);
            ctx.bezierCurveTo(x + 58, y - 18, x + 115, y - 18, x + 178, y);
            ctx.bezierCurveTo(x + 115, y + 18, x + 58, y + 18, x, y + 9);
            ctx.closePath();
            ctx.fill();
        });
        ctx.restore();
    }

    /**
     * 绘制歼-35 风格隐身战机主体。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} x 战机中心 x
     * @param {number} y 战机中心 y
     * @param {number} scale 缩放比例
     * @param {number} progress 播放进度
     */
    function drawJet(ctx, x, y, scale, progress) {
        ctx.save();
        ctx.translate(x, y);
        ctx.scale(scale, scale);
        ctx.rotate(Math.sin(progress * 10) * 0.018);

        drawAfterburners(ctx, progress);

        const bodyGradient = ctx.createLinearGradient(-210, -62, 190, 62);
        bodyGradient.addColorStop(0, "#d1d5db");
        bodyGradient.addColorStop(0.34, "#6b7280");
        bodyGradient.addColorStop(0.64, "#374151");
        bodyGradient.addColorStop(1, "#111827");

        ctx.save();
        ctx.shadowColor = "rgba(148,163,184,0.9)";
        ctx.shadowBlur = 18;

        // 主翼与机体采用多边形硬折线，体现隐身战机边缘。
        ctx.fillStyle = bodyGradient;
        ctx.beginPath();
        ctx.moveTo(-230, 0);
        ctx.lineTo(-96, -44);
        ctx.lineTo(12, -120);
        ctx.lineTo(58, -42);
        ctx.lineTo(170, -70);
        ctx.lineTo(142, -18);
        ctx.lineTo(202, 0);
        ctx.lineTo(142, 18);
        ctx.lineTo(170, 70);
        ctx.lineTo(58, 42);
        ctx.lineTo(12, 120);
        ctx.lineTo(-96, 44);
        ctx.closePath();
        ctx.fill();

        const spineGradient = ctx.createLinearGradient(-200, -16, 178, 16);
        spineGradient.addColorStop(0, "#e5e7eb");
        spineGradient.addColorStop(0.45, "#6b7280");
        spineGradient.addColorStop(1, "#1f2937");
        ctx.fillStyle = spineGradient;
        ctx.beginPath();
        ctx.moveTo(-222, 0);
        ctx.lineTo(-80, -24);
        ctx.lineTo(92, -18);
        ctx.lineTo(184, 0);
        ctx.lineTo(92, 18);
        ctx.lineTo(-80, 24);
        ctx.closePath();
        ctx.fill();

        // 机头下方深色进气道。
        ctx.fillStyle = "rgba(3,7,18,0.72)";
        ctx.beginPath();
        ctx.moveTo(-92, -33);
        ctx.lineTo(-38, -74);
        ctx.lineTo(-8, -55);
        ctx.lineTo(-60, -24);
        ctx.closePath();
        ctx.fill();
        ctx.beginPath();
        ctx.moveTo(-92, 33);
        ctx.lineTo(-38, 74);
        ctx.lineTo(-8, 55);
        ctx.lineTo(-60, 24);
        ctx.closePath();
        ctx.fill();

        // 座舱盖。
        const canopy = ctx.createLinearGradient(-148, -18, -58, 18);
        canopy.addColorStop(0, "#020617");
        canopy.addColorStop(0.55, "#1e3a8a");
        canopy.addColorStop(1, "#111827");
        ctx.fillStyle = canopy;
        ctx.beginPath();
        ctx.moveTo(-160, 0);
        ctx.bezierCurveTo(-130, -28, -78, -28, -48, 0);
        ctx.bezierCurveTo(-78, 26, -130, 26, -160, 0);
        ctx.fill();

        // 双垂尾。
        ctx.fillStyle = DARK_STEEL;
        ctx.beginPath();
        ctx.moveTo(78, -44);
        ctx.lineTo(154, -120);
        ctx.lineTo(132, -38);
        ctx.closePath();
        ctx.fill();
        ctx.beginPath();
        ctx.moveTo(78, 44);
        ctx.lineTo(154, 120);
        ctx.lineTo(132, 38);
        ctx.closePath();
        ctx.fill();

        // 中国战机识别元素：低调红星，不做过大以免影响隐身外形。
        drawRedStar(ctx, 18, -47, 15);
        drawRedStar(ctx, 18, 47, 15);

        // 面板高光线。
        ctx.strokeStyle = "rgba(229,231,235,0.34)";
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(-205, 0);
        ctx.lineTo(168, 0);
        ctx.moveTo(-70, -22);
        ctx.lineTo(86, -16);
        ctx.moveTo(-70, 22);
        ctx.lineTo(86, 16);
        ctx.stroke();

        ctx.restore();
        ctx.restore();
    }

    /**
     * 绘制低调红星机徽。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} x 中心 x
     * @param {number} y 中心 y
     * @param {number} radius 半径
     */
    function drawRedStar(ctx, x, y, radius) {
        ctx.save();
        ctx.translate(x, y);
        ctx.fillStyle = "rgba(239,68,68,0.9)";
        ctx.strokeStyle = "rgba(254,202,202,0.68)";
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        for (let i = 0; i < 10; i++) {
            const angle = -Math.PI / 2 + (i * Math.PI) / 5;
            const r = i % 2 === 0 ? radius : radius * 0.42;
            const px = Math.cos(angle) * r;
            const py = Math.sin(angle) * r;
            if (i === 0) {
                ctx.moveTo(px, py);
            } else {
                ctx.lineTo(px, py);
            }
        }
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
        ctx.restore();
    }

    /**
     * 绘制高速掠过时的音爆环。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} w 画布宽度
     * @param {number} h 画布高度
     * @param {number} progress 播放进度
     */
    function drawSonicRing(ctx, w, h, progress) {
        const ringProgress = Math.max(0, Math.min(1, (progress - 0.38) / 0.22));
        if (ringProgress <= 0 || ringProgress >= 1) {
            return;
        }

        const alpha = Math.sin(ringProgress * Math.PI);
        ctx.save();
        ctx.globalCompositeOperation = "lighter";
        ctx.strokeStyle = `rgba(224,242,254,${0.42 * alpha})`;
        ctx.lineWidth = 5;
        ctx.beginPath();
        ctx.ellipse(w * 0.5, h * 0.54, w * (0.08 + ringProgress * 0.32), h * (0.03 + ringProgress * 0.11), 0, 0, Math.PI * 2);
        ctx.stroke();
        ctx.strokeStyle = `rgba(56,189,248,${0.2 * alpha})`;
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.ellipse(w * 0.5, h * 0.54, w * (0.12 + ringProgress * 0.44), h * (0.05 + ringProgress * 0.16), 0, 0, Math.PI * 2);
        ctx.stroke();
        ctx.restore();
    }

    /**
     * 绘制战术 HUD 字幕。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} w 画布宽度
     * @param {number} h 画布高度
     * @param {number} progress 播放进度
     * @param {string} title 入场标题
     * @param {string} userInfo 用户身份信息
     */
    function drawHud(ctx, w, h, progress, title, userInfo) {
        const enter = Math.min(1, Math.max(0, (progress - 0.13) / 0.18));
        const leave = Math.min(1, Math.max(0, (1 - progress) / 0.16));
        const alpha = easeInOutSine(enter) * leave;
        const y = h * 0.18 - (1 - enter) * 26;

        ctx.save();
        ctx.globalAlpha = alpha;
        ctx.textAlign = "center";
        ctx.shadowColor = "rgba(56,189,248,0.95)";
        ctx.shadowBlur = 22;
        ctx.fillStyle = "rgba(2,6,23,0.62)";
        ctx.strokeStyle = "rgba(56,189,248,0.72)";
        ctx.lineWidth = 2;
        roundRect(ctx, w * 0.5 - 340, y - 56, 680, 120, 18);
        ctx.fill();
        ctx.stroke();

        ctx.fillStyle = "#bae6fd";
        ctx.font = "700 16px serif";
        ctx.fillText("STEALTH FIGHTER ARRIVAL", w * 0.5, y - 24);
        ctx.fillStyle = "#e0f2fe";
        ctx.font = "700 18px serif";
        ctx.fillText(userInfo, w * 0.5, y + 8, 620);
        ctx.fillStyle = "#ffffff";
        ctx.font = "900 34px serif";
        ctx.fillText(title, w * 0.5, y + 45, 620);
        ctx.restore();
    }

    /**
     * 绘制圆角矩形路径。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} x 左上角 x
     * @param {number} y 左上角 y
     * @param {number} w 宽度
     * @param {number} h 高度
     * @param {number} r 圆角半径
     */
    function roundRect(ctx, x, y, w, h, r) {
        ctx.beginPath();
        ctx.moveTo(x + r, y);
        ctx.lineTo(x + w - r, y);
        ctx.quadraticCurveTo(x + w, y, x + w, y + r);
        ctx.lineTo(x + w, y + h - r);
        ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
        ctx.lineTo(x + r, y + h);
        ctx.quadraticCurveTo(x, y + h, x, y + h - r);
        ctx.lineTo(x, y + r);
        ctx.quadraticCurveTo(x, y, x + r, y);
        ctx.closePath();
    }

    /**
     * 启动歼-35 战机入场特效。
     *
     * @param {HTMLCanvasElement} canvas 全屏特效画布
     * @param {Function} onEnd 结束回调
     * @param {object} options 特效附加参数
     * @returns {{cancel: Function}}
     */
    function start(canvas, onEnd, options = {}) {
        const ctx = canvas.getContext("2d");
        const w = canvas.width;
        const h = canvas.height;
        const speedLines = createSpeedLines(w, h);
        const title = String(options.effect_title || "中国歼-35 破空入场").trim() || "中国歼-35 破空入场";
        const userInfo = String(options.effect_user_info || "").trim();
        const startTime = performance.now();
        let animId = null;
        let finished = false;

        /**
         * 统一结束动画，手动取消时只清理不回调。
         *
         * @param {boolean} canceled 是否为手动取消
         */
        function finish(canceled) {
            if (finished) {
                return;
            }

            finished = true;
            if (animId) {
                cancelAnimationFrame(animId);
            }
            ctx.clearRect(0, 0, w, h);
            if (!canceled) {
                onEnd();
            }
        }

        /**
         * 逐帧绘制战机入场动画。
         *
         * @param {number} now 当前高精度时间
         */
        function animate(now) {
            const elapsed = now - startTime;
            const progress = Math.min(1, elapsed / DURATION);
            const entry = easeOutCubic(Math.min(1, progress / 0.62));
            const exit = easeInOutSine(Math.max(0, (progress - 0.76) / 0.24));
            const jetX = w * 1.2 - entry * w * 0.82 - exit * w * 0.58;
            const jetY = h * 0.58 + Math.sin(progress * 18) * 10;
            const scale = Math.min(1.14, Math.max(0.68, w / 1180));

            ctx.clearRect(0, 0, w, h);
            drawBackdrop(ctx, w, h, progress);
            drawSpeedLines(ctx, speedLines, w, progress);
            drawSonicRing(ctx, w, h, progress);
            drawJet(ctx, jetX, jetY, scale, progress);
            drawHud(ctx, w, h, progress, title, userInfo);

            if (progress < 1) {
                animId = requestAnimationFrame(animate);
            } else {
                finish(false);
            }
        }

        animId = requestAnimationFrame(animate);

        return {
            cancel() {
                finish(true);
            },
        };
    }

    return { start };
})();

window.J35Effect = J35Effect;
