import { PAPER_SIZE } from '../constants/colors';
import { downloadPrint } from '../utils/downloadPrint';
import { BaseDrawService } from '../core/draw/baseDraw';
import tracker from '../utils/tracker';
import { defaultShareConfig } from '../config/config';

/**
 * Canvas 相关的页面实例属性
 */
export interface PageCanvasInstance {
    data: CanvasDataState;
    canvas: Canvas | null;
    ctx: RenderingContext | null;
    boxHeight: number;
    boxWidth: number;
    drawService: BaseDrawService | null;
    setData(data: any, callback?: () => void): void;
    route: string;
    getShareOptions(): ShareOptions;
}

/**
 * Canvas 数据状态接口
 */
export interface CanvasDataState {
    hasContent: boolean;
    showShareDialog: boolean;
    boxWidth: number;
    boxHeight: number;
    functionId: string;
    currentMode?: string;
    pageTitle: string;
    subTitle?: string;
    data: any;
    setData(data: any, callback?: () => void): void;
    route: string;
}

/**
 * Canvas 初始化选项
 */
export interface InitCanvasOptions {
    /**
     * 创建绘制服务的工厂函数
     */
    createDrawService: (
        canvas: Canvas,
        ctx: RenderingContext,
        options?: Record<string, any>,
    ) => BaseDrawService;
    /**
     * 绘制服务的选项
     */
    drawServiceOptions?: Record<string, any>;
    /**
     * Canvas 初始化完成后回调
     */
    onCanvasReady?: () => void;
}

/**
 * 分享配置选项
 */
export interface ShareOptions {
    /**
     * 页面路径（相对于 mathPages 目录，例如：'missingNumber/missingNumber'）
     */
    path: string;
    title: string;
    imageUrl: string;
}

/**
 * 页面信息接口
 */
export interface PageInfo {
    title: string;
    desc?: string;
}

/**
 * 页面信息查找函数类型
 */
export type PageInfoLookup = (functionId: string) => PageInfo | undefined;

/**
 * 页面公共方法配置
 */
export interface PageCommonMethodsConfig {
    /**
     * 分享配置
     */
    shareConfig?: {
        title: string;
        imageUrl: string;
    };
    /**
     * 页面信息查找函数（可选）
     * 如果提供，initPageInfo 方法会使用它来查找页面信息
     */
    pageInfoLookup?: PageInfoLookup;
}

/**
 * 获取页面公共方法
 * 这些方法可以在所有Canvas绘制页面中复用
 * @param config 配置选项
 */
export function getPageCommonMethods(config: PageCommonMethodsConfig = {}) {
    const { shareConfig = defaultShareConfig, pageInfoLookup } = config;

    return {
        /**
         * 初始化 Canvas
         */
        initCanvas(this: PageCanvasInstance, options: InitCanvasOptions) {
            const query = wx.createSelectorQuery();
            query
                .select('#canvasWrapper')
                .boundingClientRect((rect) => {
                    if (!rect) return;

                    const { width, height } = PAPER_SIZE['A4'];
                    const boxWidth = rect.width;
                    const boxHeight = boxWidth / (width / height);

                    this.boxHeight = boxHeight;
                    this.boxWidth = boxWidth;

                    this.setData({ boxWidth, boxHeight });

                    const canvas = wx
                        .createSelectorQuery()
                        .select('#canvasContent');
                    canvas.fields({ node: true, size: true }).exec((res) => {
                        if (res[0]) {
                            const canvasNode = res[0].node;
                            const ctx = canvasNode.getContext('2d');
                            const dpr = wx.getSystemInfoSync().pixelRatio;

                            canvasNode.width = boxWidth * dpr;
                            canvasNode.height = boxHeight * dpr;
                            ctx.scale(dpr, dpr);

                            this.canvas = canvasNode;
                            this.ctx = ctx;

                            // 创建绘制服务
                            const drawServiceOptions = {
                                title: this.data.pageTitle,
                                subTitle: this.data.subTitle || '',
                                ...options.drawServiceOptions,
                            };

                            this.drawService = options.createDrawService(
                                canvasNode,
                                ctx,
                                drawServiceOptions,
                            );

                            // 执行初始化完成回调
                            if (options.onCanvasReady) {
                                options.onCanvasReady.call(this);
                            }
                        }
                    });
                })
                .exec();
        },

        /**
         * 导出打印
         */
        async exportToPrint(this: PageCanvasInstance) {
            await downloadPrint(this.canvas, {
                errorToast: '请先生成内容',
                trackerName: this.data.pageTitle,
                trackerMode: this.data.currentMode,
            });
        },

        getShareOptions(this: PageCanvasInstance): ShareOptions {
            const route = this.route || '';
            const { functionId, currentMode } = this.data;
            const currentModeQuery = currentMode ? `&mode=${currentMode}` : '';
            const path = `${route}?id=${functionId}${currentModeQuery}`;

            console.log('getShareOptions path', path);
            return {
                ...shareConfig,
                path,
            };
        },

        /**
         * 分享小程序
         */
        onShareAppMessage(this: PageCanvasInstance) {
            // 上报分享埋点
            tracker.reportShare(this.data.pageTitle);

            return this.getShareOptions();
        },

        /**
         * 分享到朋友圈
         */
        onShareTimeline(this: PageCanvasInstance) {
            console.log('onShareTimeline');
            // 上报分享埋点
            tracker.reportShare(this.data.pageTitle);
            return this.getShareOptions();
        },

        /**
         * 关闭分享引导弹窗
         */
        onCloseShareDialog(this: PageCanvasInstance) {
            this.setData({ showShareDialog: false });
        },

        /**
         * 分享成功回调
         */
        async onShareSuccess(this: PageCanvasInstance) {
            this.setData({ showShareDialog: false });
            if (this.canvas) {
                // 分享成功后下载（不限制次数）
                await downloadPrint(this.canvas, {
                    errorToast: '请先生成内容',
                    trackerName: this.data.pageTitle,
                    trackerMode: this.data.currentMode,
                });
            }
        },

        /**
         * 初始化页面信息
         *
         * 支持两种调用方式：
         * 1. initPageInfo(functionId, defaultTitle) - 如果有 pageInfoLookup，会尝试查找；否则使用 defaultTitle
         * 2. initPageInfo({ title, desc, functionId }) - 直接提供页面信息
         */
        initPageInfo(
            this: PageCanvasInstance,
            functionIdOrOptions:
                | string
                | { title: string; desc?: string; functionId: string },
            defaultTitle?: string,
        ) {
            let functionId: string;
            let title: string;
            let desc: string = '';

            // 判断调用方式
            if (typeof functionIdOrOptions === 'string') {
                // 方式1: initPageInfo(functionId, defaultTitle)
                functionId = functionIdOrOptions;
                title = defaultTitle || '';

                // 如果有 pageInfoLookup，尝试查找
                if (pageInfoLookup) {
                    const pageInfo = pageInfoLookup(functionId);
                    if (pageInfo) {
                        title = pageInfo.title;
                        desc = pageInfo.desc || '';
                    }
                }
            } else {
                // 方式2: initPageInfo({ title, desc, functionId })
                functionId = functionIdOrOptions.functionId;
                title = functionIdOrOptions.title;
                desc = functionIdOrOptions.desc || '';
            }

            this.setData({
                pageTitle: title,
                subTitle: desc,
                functionId,
            });

            wx.setNavigationBarTitle({ title });
        },
    };
}

/**
 * 应用页面公共方法的辅助函数
 * 自动混入公共方法，简化页面代码
 * @param pageOptions 页面选项
 * @param config 公共方法配置
 * @returns 合并后的页面选项
 */
export function applyPageMixin(
    pageOptions: any,
    config: PageCommonMethodsConfig = {},
) {
    const commonMethods = getPageCommonMethods(config);

    // 提取 pageOptions 中的 data（如果有）
    const pageData = pageOptions.data || {};

    // 合并页面选项和公共方法
    // 注意：pageOptions 放在后面，这样页面可以覆盖公共方法
    const mergedOptions: any = {
        ...commonMethods,
        ...pageOptions,
        // 处理 data 的合并（需要特殊处理，避免覆盖）
        data: {
            ...pageData,
        },
    };

    return mergedOptions;
}

/**
 * 创建页面的便捷函数
 * 自动应用公共方法并注册为页面
 * @param pageOptions 页面选项
 * @param config 公共方法配置
 */
export function createPage(
    pageOptions: any,
    config: PageCommonMethodsConfig = {},
) {
    Page(applyPageMixin(pageOptions, config));
}
