import { defineStore } from 'pinia';
import { ref, watch } from 'vue';

export type LogLevel = 'info' | 'warn' | 'error' | 'debug';

export interface LogEntry {
    id: number;
    time: string;
    level: LogLevel;
    module: string;
    message: string;
    detail?: any;
}

const MAX_LOGS = 500;
const STORAGE_KEY = 'qz-app-logs';
const LEVEL_ORDER: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };

function loadFromStorage(): LogEntry[] {
    try {
        const raw = localStorage.getItem(STORAGE_KEY);
        if (raw) {
            const parsed = JSON.parse(raw);
            if (Array.isArray(parsed)) return parsed as LogEntry[];
        }
    } catch {
        // ignore
    }
    return [];
}

export const useLogStore = defineStore('log', () => {
    const logs = ref<LogEntry[]>(loadFromStorage());
    let nextId = logs.value.length > 0 ? Math.max(...logs.value.map((l) => l.id)) + 1 : 1;

    watch(
        logs,
        (newLogs) => {
            try {
                localStorage.setItem(STORAGE_KEY, JSON.stringify(newLogs));
            } catch {
                // ignore quota issues
            }
        },
        { deep: true }
    );

    const add = (level: LogLevel, module: string, message: string, detail?: any) => {
        const now = new Date();
        const hh = now.getHours().toString().padStart(2, '0');
        const mm = now.getMinutes().toString().padStart(2, '0');
        const ss = now.getSeconds().toString().padStart(2, '0');
        const ms = now.getMilliseconds().toString().padStart(3, '0');

        // Error 对象属性不可枚举（JSON.stringify 会得到 {}），这里先规范化
        let normalizedDetail = detail;
        if (detail instanceof Error) {
            normalizedDetail = {
                name: detail.name,
                message: detail.message,
                stack: detail.stack,
                cause: (detail as any).cause,
                __isError: true,
            };
        } else if (detail && typeof detail === 'object') {
            // 避免 Proxy 等响应式包装的干扰 — 简单浅拷贝为纯对象
            try {
                normalizedDetail = JSON.parse(JSON.stringify(detail, (_, v) => {
                    if (v instanceof Error) {
                        return { name: v.name, message: v.message, stack: v.stack, __isError: true };
                    }
                    return v;
                }));
            } catch {
                normalizedDetail = String(detail);
            }
        }

        const entry: LogEntry = {
            id: nextId++,
            time: `${hh}:${mm}:${ss}.${ms}`,
            level,
            module,
            message,
            detail: normalizedDetail,
        };

        logs.value.push(entry);
        if (logs.value.length > MAX_LOGS) {
            logs.value = logs.value.slice(-MAX_LOGS);
        }

        // 同步到浏览器控制台，方便调试
        const consoleArgs = [`[${entry.time}] [${level.toUpperCase()}] [${module}]`, message];
        if (detail !== undefined) consoleArgs.push(detail);
        try {
            if (level === 'error') console.error(...consoleArgs);
            else if (level === 'warn') console.warn(...consoleArgs);
            else if (level === 'debug') console.debug(...consoleArgs);
            else console.log(...consoleArgs);
        } catch {
            // ignore
        }
    };

    const info = (module: string, message: string, detail?: any) => add('info', module, message, detail);
    const warn = (module: string, message: string, detail?: any) => add('warn', module, message, detail);
    const error = (module: string, message: string, detail?: any) => add('error', module, message, detail);
    const debug = (module: string, message: string, detail?: any) => add('debug', module, message, detail);

    const clear = () => {
        logs.value = [];
        nextId = 1;
    };

    const filter = (module?: string, level?: LogLevel) => {
        return logs.value.filter((l) => {
            if (module && l.module !== module) return false;
            if (level && LEVEL_ORDER[l.level] < LEVEL_ORDER[level]) return false;
            return true;
        });
    };

    const moduleList = () => {
        const set = new Set<string>();
        for (const l of logs.value) set.add(l.module);
        return Array.from(set).sort();
    };

    const countByLevel = () => {
        const c = { info: 0, warn: 0, error: 0, debug: 0 };
        for (const l of logs.value) c[l.level]++;
        return c;
    };

    return {
        logs,
        info,
        warn,
        error,
        debug,
        add,
        clear,
        filter,
        moduleList,
        countByLevel,
    };
});
