/**
 * Terminal 实例封装
 * 职责：封装 XTerm 实例 + 连接策略，管理完整的终端生命周期
 */

import { Terminal as XTerm } from 'xterm';
import { FitAddon } from '@xterm/addon-fit';
import { WebLinksAddon } from '@xterm/addon-web-links';
import { SearchAddon } from '@xterm/addon-search';
import { BaseConnectionStrategy, ConnectionStatus } from '../strategies/BaseConnectionStrategy';
import type { TerminalConnectionConfig } from '../types';

export interface TerminalDisplayConfig {
    cursorBlink?: boolean;
    fontSize?: number;
    fontFamily?: string;
    theme?: any;
    rows?: number;
    cols?: number;
    scrollback?: number;
}

export interface TerminalInstanceConfig {
    id: string;
    connection: BaseConnectionStrategy;  // 实际的连接策略实例
    display?: TerminalDisplayConfig;
}

// Manager 使用的配置（传入配置，Manager 负责创建策略）
export interface TerminalInstanceCreateConfig {
    id: string;
    connectionConfig: TerminalConnectionConfig;  // 连接配置
    display?: TerminalDisplayConfig;
}

export type StateChangeCallback = (state: {
    status: ConnectionStatus;
    errorMessage?: string;
}) => void;

/**
 * Terminal 实例类
 * 独立于 React 组件生命周期，可以跨组件挂载/卸载复用
 */
export class TerminalInstance {
    private xterm: XTerm;
    private fitAddon: FitAddon;
    private searchAddon: SearchAddon;
    private webLinksAddon: WebLinksAddon;
    
    private mounted = false;
    private currentContainer: HTMLElement | null = null;
    private connectionStrategy: BaseConnectionStrategy;
    
    private stateListeners: Set<StateChangeCallback> = new Set();
    private unsubscribers: Array<() => void> = [];
    private auditShown: boolean = false;
    private firstOutputReceived: boolean = false;  // 追踪是否已接收首次output

    constructor(private config: TerminalInstanceConfig) {
        // 初始化 XTerm
        const display = config.display || {};
        this.xterm = new XTerm({
            cursorBlink: display.cursorBlink ?? true,
            fontSize: display.fontSize ?? 14,
            fontFamily: display.fontFamily ?? 'Consolas, "Courier New", monospace',
            theme: display.theme, // 主题由外部传入，保持主题系统的完整性
            rows: display.rows ?? 30,
            cols: display.cols ?? 100,
            scrollback: display.scrollback ?? 10000,
        });

        // 初始化插件
        this.fitAddon = new FitAddon();
        this.searchAddon = new SearchAddon();
        this.webLinksAddon = new WebLinksAddon();

        this.xterm.loadAddon(this.fitAddon);
        this.xterm.loadAddon(this.searchAddon);
        this.xterm.loadAddon(this.webLinksAddon);

        // 绑定连接策略
        this.connectionStrategy = config.connection;
        this.setupConnectionListeners();
        this.setupTerminalListeners();
    }

    /**
     * 挂载到 DOM
     */
    mount(container: HTMLElement): void {
        if (!container) {
            console.warn(`[TerminalInstance ${this.config.id}] No container provided`);
            return;
        }

        // 如果已经挂载到其他容器，先卸载
        if (this.mounted && this.currentContainer !== container) {
            this.unmount();
        }

        // 只在第一次或切换容器时调用 open
        if (!this.mounted) {
            this.xterm.open(container);
        }

        this.currentContainer = container;
        this.mounted = true;

        // 自适应尺寸并通知后端
        setTimeout(() => {
            this.fitAddon.fit();
            // 发送终端尺寸给后端
            const cols = this.xterm.cols;
            const rows = this.xterm.rows;
            this.connectionStrategy.resize(cols, rows);
        }, 100);

    }

    /**
     * 从 DOM 卸载（但不销毁实例）
     */
    unmount(): void {
        if (!this.mounted) return;

        // XTerm 没有直接的 unmount 方法，我们只需标记状态
        this.currentContainer = null;
        this.mounted = false;

    }

    /**
     * 连接到服务器
     */
    async connect(): Promise<void> {
        await this.connectionStrategy.connect();
    }

    /**
     * 断开连接
     */
    disconnect(): void {
        this.connectionStrategy.disconnect();
    }

    /**
     * 获取 XTerm 实例（用于 UI 层操作）
     */
    getXTerm(): XTerm {
        return this.xterm;
    }

    /**
     * 获取 FitAddon（用于尺寸调整）
     */
    getFitAddon(): FitAddon {
        return this.fitAddon;
    }

    /**
     * 获取 SearchAddon（用于搜索功能）
     */
    getSearchAddon(): SearchAddon {
        return this.searchAddon;
    }

    /**
     * 获取当前连接状态
     */
    getConnectionStatus(): ConnectionStatus {
        return this.connectionStrategy.getStatus();
    }

    /**
     * 获取当前状态
     */
    getState(): { status: ConnectionStatus; errorMessage?: string } {
        return {
            status: this.connectionStrategy.getStatus(),
            errorMessage: undefined,
        };
    }

    /**
     * 订阅状态变化
     */
    onStateChange(callback: StateChangeCallback): () => void {
        this.stateListeners.add(callback);
        return () => this.stateListeners.delete(callback);
    }

    /**
     * 发送输入
     */
    sendInput(data: string): void {
        this.connectionStrategy.sendInput(data);
    }

    /**
     * 发送尺寸变化到后端
     */
    sendResize(cols: number, rows: number): void {
        this.connectionStrategy.resize(cols, rows);
    }

    /**
     * 设置终端配置（字体大小、主题等）
     */
    updateDisplay(config: Partial<TerminalDisplayConfig>): void {
        if (config.fontSize !== undefined) {
            this.xterm.options.fontSize = config.fontSize;
        }
        if (config.theme !== undefined) {
            this.xterm.options.theme = config.theme;
        }
        
        // 更新后重新适配尺寸
        setTimeout(() => this.fitAddon.fit(), 50);
    }

    /**
     * 清屏
     */
    clear(): void {
        this.xterm.clear();
    }

    /**
     * 写入文本
     */
    write(data: string): void {
        this.xterm.write(data);
    }

    /**
     * 写入一行文本
     */
    writeln(data: string): void {
        this.xterm.writeln(data);
    }

    /**
     * 显示审计警告（只显示一次）
     */
    showAudit(companyName: string, customMessage?: string): boolean {
        if (this.auditShown) {
            return false;
        }

        if (customMessage) {
            this.writeln(`\r\n\x1b[33m${customMessage}\x1b[0m\r\n`);
        } else {
            this.writeln('\r\n\x1b[33m┌─────────────────────────────────────────────────────────────\x1b[0m');
            this.writeln(`\x1b[33m│ ⚠️  ${companyName} - 安全提示\x1b[0m`);
            this.writeln('\x1b[33m│ 本次会话将被全程审计记录\x1b[0m');
            this.writeln('\x1b[33m│ • 所有操作命令、输入、输出都将被完整记录\x1b[0m');
            this.writeln('\x1b[33m│ • 审计日志用于安全审查、故障排查和合规要求\x1b[0m');
            this.writeln('\x1b[33m│ • 请规范操作，遵守企业信息安全管理制度\x1b[0m');
            this.writeln('\x1b[33m└─────────────────────────────────────────────────────────────\x1b[0m\r\n');
        }

        this.auditShown = true;
        
        setTimeout(() => {
            this.fitAddon.fit();
        }, 100);

        return true;
    }

    /**
     * 重置审计显示状态（重连时使用）
     */
    resetAudit(): void {
        this.auditShown = false;
    }

    /**
     * 获取选中内容
     */
    getSelection(): string {
        return this.xterm.getSelection();
    }

    /**
     * 销毁实例（完全清理）
     */
    dispose(): void {

        // 清理连接
        this.disconnect();

        // 取消所有订阅
        this.unsubscribers.forEach(unsub => unsub());
        this.unsubscribers = [];

        // 清理状态监听器
        this.stateListeners.clear();

        // 销毁 XTerm
        if (this.xterm) {
            this.xterm.dispose();
        }

        this.mounted = false;
        this.currentContainer = null;
    }

    /**
     * 设置连接策略的监听器
     */
    private setupConnectionListeners(): void {
        // 监听消息接收
        const unsubMessage = this.connectionStrategy.onMessage((data) => {
            this.xterm.write(data);
            
            // 首次接收output时，触发resize以正确适应窗口大小
            if (!this.firstOutputReceived && data && data.length > 0) {
                this.firstOutputReceived = true;
                // 延迟一点确保DOM已渲染
                setTimeout(() => {
                    this.fitAddon.fit();
                    // 发送终端尺寸给后端
                    const cols = this.xterm.cols;
                    const rows = this.xterm.rows;
                    this.connectionStrategy.resize(cols, rows);
                }, 50);
            }
        });

        // 监听状态变化
        const unsubStatus = this.connectionStrategy.onStatusChange((status) => {
            this.notifyStateChange({ status });
        });

        // 监听错误
        const unsubError = this.connectionStrategy.onError((error) => {
            this.xterm.writeln(`\r\n\x1b[31m错误: ${error}\x1b[0m\r\n`);
            this.notifyStateChange({ 
                status: this.connectionStrategy.getStatus(), 
                errorMessage: error 
            });
        });

        this.unsubscribers.push(unsubMessage, unsubStatus, unsubError);
    }

    /**
     * 设置终端事件监听器
     */
    private setupTerminalListeners(): void {
        // 监听用户输入
        this.xterm.onData((data) => {
            this.sendInput(data);
        });

        // 监听尺寸变化
        this.xterm.onResize((size) => {
            this.sendResize(size.cols, size.rows);
        });
    }

    /**
     * 通知状态变化
     */
    private notifyStateChange(state: { status: ConnectionStatus; errorMessage?: string }): void {
        this.stateListeners.forEach(listener => listener(state));
    }
}
