/**
 * 文件功能：聊天室东风-5C洲际导弹发射预览特效
 *
 * 使用全屏透明 Canvas 绘制风格化洲际导弹升空、尾焰、烟尘冲击波、
 * 雷达扫描网格和测试 HUD。该效果只用于聊天室视觉预览，不表达真实装备参数。
 */

const Df5cEffect = (() => {
    const DURATION = 8200;
    const FIRE = "#fb923c";
    const HOT = "#fef3c7";
    const RED = "#dc2626";
    const BODY = "#e5e7eb";
    const BODY_DARK = "#64748b";

    /**
     * 缓入缓出曲线，用于导弹升空和 HUD 动画。
     *
     * @param {number} t 0 到 1 的进度
     * @returns {number}
     */
    function easeInOutCubic(t) {
        return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
    }

    /**
     * 缓出曲线，用于烟尘扩散。
     *
     * @param {number} t 0 到 1 的进度
     * @returns {number}
     */
    function easeOutCubic(t) {
        return 1 - Math.pow(1 - t, 3);
    }

    /**
     * 创建尾焰和烟尘粒子。
     *
     * @param {number} count 粒子数量
     * @returns {Array<Record<string, number>>}
     */
    function createParticles(count) {
        return Array.from({ length: count }, () => ({
            angle: Math.random() * Math.PI * 2,
            spread: 0.3 + Math.random() * 1.3,
            speed: 0.4 + Math.random() * 2.4,
            size: 4 + Math.random() * 18,
            alpha: 0.12 + Math.random() * 0.6,
            phase: Math.random() * Math.PI * 2,
        }));
    }

    /**
     * 绘制夜空、雷达网格和扫描线。
     *
     * @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.14) * Math.min(1, (1 - progress) / 0.12);
        const sky = ctx.createLinearGradient(0, 0, 0, h);
        sky.addColorStop(0, `rgba(2,6,23,${0.86 * fade})`);
        sky.addColorStop(0.58, `rgba(15,23,42,${0.62 * fade})`);
        sky.addColorStop(1, `rgba(30,41,59,${0.26 * fade})`);
        ctx.fillStyle = sky;
        ctx.fillRect(0, 0, w, h);

        ctx.save();
        ctx.globalAlpha = fade;
        ctx.strokeStyle = "rgba(56,189,248,0.16)";
        ctx.lineWidth = 1;
        for (let x = -w; x < w * 2; x += 72) {
            ctx.beginPath();
            ctx.moveTo(x + progress * 120, 0);
            ctx.lineTo(x - h * 0.55 + progress * 120, h);
            ctx.stroke();
        }
        for (let y = h * 0.2; y < h; y += 46) {
            ctx.beginPath();
            ctx.moveTo(0, y + Math.sin(progress * 18 + y) * 2);
            ctx.lineTo(w, y + Math.cos(progress * 14 + y) * 2);
            ctx.stroke();
        }

        ctx.strokeStyle = "rgba(248,113,113,0.34)";
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.arc(w * 0.16, h * 0.76, w * (0.18 + progress * 0.22), -Math.PI * 0.95, -Math.PI * 0.12);
        ctx.stroke();

        const beamAngle = -Math.PI * 0.85 + progress * Math.PI * 1.15;
        ctx.strokeStyle = "rgba(34,211,238,0.34)";
        ctx.lineWidth = 3;
        ctx.beginPath();
        ctx.moveTo(w * 0.16, h * 0.76);
        ctx.lineTo(w * 0.16 + Math.cos(beamAngle) * w * 0.42, h * 0.76 + Math.sin(beamAngle) * w * 0.42);
        ctx.stroke();
        ctx.restore();
    }

    /**
     * 绘制发射井底座、光柱和冲击波。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} w 画布宽度
     * @param {number} h 画布高度
     * @param {number} progress 播放进度
     */
    function drawLaunchPad(ctx, w, h, progress) {
        const ignition = Math.min(1, progress / 0.24);
        const pulse = Math.sin(progress * Math.PI * 12) * 0.5 + 0.5;
        const cx = w * 0.18;
        const cy = h * 0.78;

        ctx.save();
        ctx.globalCompositeOperation = "lighter";
        const beam = ctx.createRadialGradient(cx, cy, 0, cx, cy, h * 0.42);
        beam.addColorStop(0, `rgba(251,146,60,${0.54 * ignition})`);
        beam.addColorStop(0.3, `rgba(254,243,199,${0.18 * ignition})`);
        beam.addColorStop(1, "rgba(0,0,0,0)");
        ctx.fillStyle = beam;
        ctx.fillRect(0, 0, w, h);

        ctx.strokeStyle = `rgba(251,146,60,${(0.32 + pulse * 0.2) * ignition})`;
        ctx.lineWidth = 5;
        ctx.beginPath();
        ctx.ellipse(cx, cy, w * (0.06 + progress * 0.28), h * (0.025 + progress * 0.08), 0, 0, Math.PI * 2);
        ctx.stroke();
        ctx.restore();

        ctx.save();
        ctx.fillStyle = "rgba(15,23,42,0.82)";
        ctx.beginPath();
        ctx.ellipse(cx, cy + 18, w * 0.12, h * 0.035, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.strokeStyle = "rgba(148,163,184,0.7)";
        ctx.lineWidth = 3;
        ctx.stroke();
        ctx.restore();
    }

    /**
     * 绘制尾焰和烟尘。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {Array<Record<string, number>>} particles 粒子数组
     * @param {number} tailX 尾部 x
     * @param {number} tailY 尾部 y
     * @param {number} progress 播放进度
     */
    function drawExhaust(ctx, particles, tailX, tailY, progress) {
        ctx.save();
        ctx.globalCompositeOperation = "lighter";
        particles.forEach((particle, index) => {
            const t = (progress * 3.2 + index * 0.013) % 1;
            const spread = easeOutCubic(t) * 118 * particle.spread;
            const x = tailX - spread * 0.62 + Math.cos(particle.angle) * spread * 0.36;
            const y = tailY + spread * 0.86 + Math.sin(particle.angle + particle.phase) * spread * 0.24;
            const alpha = particle.alpha * (1 - t);
            const radius = particle.size * (0.7 + t * 2.4);

            ctx.globalAlpha = alpha;
            ctx.fillStyle = t < 0.34 ? HOT : t < 0.62 ? FIRE : "rgba(148,163,184,0.9)";
            ctx.shadowColor = t < 0.55 ? FIRE : "rgba(148,163,184,0.8)";
            ctx.shadowBlur = radius * 1.2;
            ctx.beginPath();
            ctx.ellipse(x, y, radius * 0.9, radius * 1.35, -0.38, 0, Math.PI * 2);
            ctx.fill();
        });
        ctx.restore();
    }

    /**
     * 绘制东风-5C风格化导弹。
     *
     * @param {CanvasRenderingContext2D} ctx Canvas 上下文
     * @param {number} x 导弹中心 x
     * @param {number} y 导弹中心 y
     * @param {number} scale 缩放比例
     * @param {number} progress 播放进度
     */
    function drawMissile(ctx, x, y, scale, progress) {
        ctx.save();
        ctx.translate(x, y);
        // 导弹沿左下到右上的轨迹飞行，箭体头部必须朝右上，尾焰才会落在后方。
        ctx.rotate(0.62 + Math.sin(progress * 7) * 0.012);
        ctx.scale(scale, scale);

        ctx.save();
        ctx.shadowColor = "rgba(251,146,60,0.9)";
        ctx.shadowBlur = 26;
        ctx.fillStyle = "rgba(251,146,60,0.86)";
        ctx.beginPath();
        ctx.moveTo(-28, 170);
        ctx.lineTo(0, 260);
        ctx.lineTo(28, 170);
        ctx.closePath();
        ctx.fill();
        ctx.fillStyle = "rgba(254,243,199,0.86)";
        ctx.beginPath();
        ctx.moveTo(-12, 176);
        ctx.lineTo(0, 236);
        ctx.lineTo(12, 176);
        ctx.closePath();
        ctx.fill();
        ctx.restore();

        const body = ctx.createLinearGradient(-44, -178, 44, 168);
        body.addColorStop(0, "#f8fafc");
        body.addColorStop(0.45, BODY);
        body.addColorStop(1, BODY_DARK);
        ctx.fillStyle = body;
        roundRect(ctx, -42, -156, 84, 326, 40);
        ctx.fill();

        ctx.fillStyle = RED;
        ctx.beginPath();
        ctx.moveTo(-42, -126);
        ctx.quadraticCurveTo(0, -214, 42, -126);
        ctx.lineTo(42, -92);
        ctx.lineTo(-42, -92);
        ctx.closePath();
        ctx.fill();

        ctx.fillStyle = "#111827";
        ctx.fillRect(-42, -74, 84, 10);
        ctx.fillRect(-42, 74, 84, 10);
        ctx.fillStyle = "rgba(239,68,68,0.92)";
        ctx.fillRect(-42, -22, 84, 30);

        ctx.fillStyle = "#111827";
        ctx.font = "900 30px serif";
        ctx.textAlign = "center";
        ctx.fillText("DF-5C", 0, 50);
        ctx.fillStyle = "#fef3c7";
        ctx.font = "900 20px serif";
        ctx.fillText("★", 0, -1);

        ctx.fillStyle = "#334155";
        ctx.beginPath();
        ctx.moveTo(-42, 102);
        ctx.lineTo(-104, 166);
        ctx.lineTo(-42, 152);
        ctx.closePath();
        ctx.fill();
        ctx.beginPath();
        ctx.moveTo(42, 102);
        ctx.lineTo(104, 166);
        ctx.lineTo(42, 152);
        ctx.closePath();
        ctx.fill();

        ctx.strokeStyle = "rgba(255,255,255,0.42)";
        ctx.lineWidth = 3;
        ctx.beginPath();
        ctx.moveTo(-20, -112);
        ctx.lineTo(-20, 130);
        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.1) / 0.18));
        const leave = Math.min(1, Math.max(0, (1 - progress) / 0.14));
        const alpha = easeInOutCubic(enter) * leave;
        const y = h * 0.16 - (1 - enter) * 20;

        ctx.save();
        ctx.globalAlpha = alpha;
        ctx.textAlign = "center";
        ctx.fillStyle = "rgba(15,23,42,0.68)";
        ctx.strokeStyle = "rgba(248,113,113,0.72)";
        ctx.lineWidth = 2;
        roundRect(ctx, w * 0.5 - 350, y - 56, 700, 120, 18);
        ctx.fill();
        ctx.stroke();
        ctx.shadowColor = "rgba(248,113,113,0.95)";
        ctx.shadowBlur = 22;
        ctx.fillStyle = "#fee2e2";
        ctx.font = "700 16px serif";
        ctx.fillText("DF-5C STRATEGIC LAUNCH PREVIEW", w * 0.5, y - 24);
        ctx.fillStyle = "#fecaca";
        ctx.font = "700 18px serif";
        ctx.fillText(userInfo, w * 0.5, y + 8, 640);
        ctx.fillStyle = "#ffffff";
        ctx.font = "900 34px serif";
        ctx.fillText(title, w * 0.5, y + 45, 640);
        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();
    }

    /**
     * 启动东风-5C洲际导弹发射预览特效。
     *
     * @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 particles = createParticles(120);
        const title = String(options.effect_title || "东风-5C 洲际导弹 升空").trim() || "东风-5C 洲际导弹 升空";
        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 progress = Math.min(1, (now - startTime) / DURATION);
            const launch = easeInOutCubic(Math.min(1, progress / 0.78));
            const launchX = w * (0.18 + launch * 0.66);
            const launchY = h * (0.78 - launch * 0.95);
            const scale = Math.min(1.08, Math.max(0.7, w / 1240));
            const tailX = launchX - Math.sin(0.62) * 168 * scale;
            const tailY = launchY + Math.cos(0.62) * 168 * scale;

            ctx.clearRect(0, 0, w, h);
            drawBackdrop(ctx, w, h, progress);
            drawLaunchPad(ctx, w, h, progress);
            drawExhaust(ctx, particles, tailX, tailY, progress);
            drawMissile(ctx, launchX, launchY, 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.Df5cEffect = Df5cEffect;
