/**
 * WEB远程控制中间层
 * 介于API模拟和远程桌面之间的重要层级
 * 通过Web技术实现远程控制，比API模拟更灵活，比远程桌面更轻量
 */

import { chromium, Browser, Page } from 'playwright';
import { WebSocketServer, WebSocket } from 'ws';
import { createServer } from 'http';
import * as fs from 'fs';
import * as path from 'path';

interface WebRemoteConfig {
  port: number;
  headless: boolean;
  proxy?: string;
  viewport: { width: number; height: number };
  userAgent: string;
}

interface WebSession {
  id: string;
  platform: string;
  page: Page;
  browser: Browser;
  status: 'ready' | 'active' | 'error' | 'closed';
  lastActivity: Date;
  currentUrl: string;
  title: string;
  cookies: any[];
  localStorage: Record<string, any>;
}

interface WebCommand {
  type: 'navigate' | 'click' | 'type' | 'scroll' | 'screenshot' | 'eval' | 'cookies' | 'storage';
  action: string;
  data: any;
  sessionId: string;
}

interface WebResponse {
  success: boolean;
  type: string;
  data?: any;
  error?: string;
  sessionId: string;
  timestamp: number;
}

/**
 * WEB远程控制服务
 */
export class WebRemoteService {
  private config: WebRemoteConfig;
  private sessions: Map<string, WebSession> = new Map();
  private wss: WebSocketServer;
  private browser: Browser | null = null;

  constructor(config: WebRemoteConfig) {
    this.config = config;
    
    // 创建HTTP服务器
    const server = createServer((req, res) => {
      this.handleHttpRequest(req, res);
    });

    // 创建WebSocket服务器
    this.wss = new WebSocketServer({ server });
    server.listen(config.port);

    this.setupWebSocketHandlers();
    this.initializeBrowser();
  }

  /**
   * 初始化浏览器
   */
  private async initializeBrowser(): Promise<void> {
    try {
      this.browser = await chromium.launch({
        headless: this.config.headless,
        proxy: this.config.proxy ? { server: this.config.proxy } : undefined,
        args: [
          '--disable-web-security',
          '--disable-features=IsolateOrigins,site-per-process',
          '--allow-running-insecure-content',
          '--disable-blink-features=AutomationControlled'
        ]
      });

      console.log('WEB远程控制服务浏览器初始化完成');
    } catch (error) {
      console.error('浏览器初始化失败:', error);
    }
  }

  /**
   * 设置WebSocket处理器
   */
  private setupWebSocketHandlers(): void {
    this.wss.on('connection', (ws: WebSocket) => {
      console.log('WEB远程控制客户端连接建立');
      
      ws.on('message', async (data: Buffer) => {
        try {
          const command: WebCommand = JSON.parse(data.toString());
          const response = await this.handleWebCommand(command);
          ws.send(JSON.stringify(response));
        } catch (error) {
          ws.send(JSON.stringify({
            success: false,
            type: 'error',
            error: error instanceof Error ? error.message : '命令处理失败',
            sessionId: 'unknown',
            timestamp: Date.now()
          }));
        }
      });

      ws.on('close', () => {
        console.log('WEB远程控制客户端连接关闭');
      });
    });
  }

  /**
   * 处理HTTP请求
   */
  private handleHttpRequest(req: any, res: any): void {
    const { url, method } = req;
    
    res.setHeader('Content-Type', 'application/json');
    res.setHeader('Access-Control-Allow-Origin', '*');

    if (url === '/health' && method === 'GET') {
      res.writeHead(200);
      res.end(JSON.stringify({
        status: 'healthy',
        service: 'web-remote',
        activeSessions: this.sessions.size,
        browser: this.browser ? 'connected' : 'disconnected',
        timestamp: Date.now()
      }));
    } else if (url === '/sessions' && method === 'GET') {
      res.writeHead(200);
      res.end(JSON.stringify(this.getSessionList()));
    } else {
      res.writeHead(404);
      res.end(JSON.stringify({ error: '接口不存在' }));
    }
  }

  /**
   * 创建WEB会话
   */
  async createSession(platform: string, initialUrl?: string): Promise<WebSession> {
    if (!this.browser) {
      await this.initializeBrowser();
    }

    const context = await this.browser!.newContext({
      viewport: this.config.viewport,
      userAgent: this.config.userAgent,
      ignoreHTTPSErrors: true
    });

    const page = await context.newPage();
    
    // 设置页面事件监听
    await this.setupPageEventListeners(page);

    const sessionId = this.generateSessionId();
    const session: WebSession = {
      id: sessionId,
      platform,
      page,
      browser: this.browser!,
      status: 'ready',
      lastActivity: new Date(),
      currentUrl: '',
      title: '',
      cookies: [],
      localStorage: {}
    };

    this.sessions.set(sessionId, session);

    // 如果有初始URL，导航到该页面
    if (initialUrl) {
      await this.navigateToUrl(session, initialUrl);
    }

    console.log(`WEB会话创建成功: ${sessionId} (${platform})`);
    return session;
  }

  /**
   * 设置页面事件监听器
   */
  private async setupPageEventListeners(page: Page): Promise<void> {
    // 监听页面导航
    page.on('framenavigated', async (frame) => {
      if (frame === page.mainFrame()) {
        const session = this.findSessionByPage(page);
        if (session) {
          session.currentUrl = frame.url();
          session.lastActivity = new Date();
        }
      }
    });

    // 监听页面加载完成
    page.on('load', async () => {
      const session = this.findSessionByPage(page);
      if (session) {
        session.title = await page.title();
        session.lastActivity = new Date();
        
        // 获取当前页面的cookies和localStorage
        try {
          session.cookies = await page.context().cookies();
          session.localStorage = await page.evaluate(() => {
            const storage: Record<string, any> = {};
            for (let i = 0; i < localStorage.length; i++) {
              const key = localStorage.key(i);
              if (key) {
                storage[key] = localStorage.getItem(key);
              }
            }
            return storage;
          });
        } catch (error) {
          console.warn('获取页面存储信息失败:', error);
        }
      }
    });

    // 监听控制台消息
    page.on('console', (msg) => {
      const session = this.findSessionByPage(page);
      if (session) {
        console.log(`WEB会话 ${session.id} 控制台:`, msg.text());
      }
    });

    // 监听页面错误
    page.on('pageerror', (error) => {
      const session = this.findSessionByPage(page);
      if (session) {
        console.error(`WEB会话 ${session.id} 页面错误:`, error);
        session.status = 'error';
      }
    });
  }

  /**
   * 通过页面查找会话
   */
  private findSessionByPage(page: Page): WebSession | undefined {
    for (const session of this.sessions.values()) {
      if (session.page === page) {
        return session;
      }
    }
    return undefined;
  }

  /**
   * 处理WEB命令
   */
  private async handleWebCommand(command: WebCommand): Promise<WebResponse> {
    const session = this.sessions.get(command.sessionId);
    if (!session) {
      return {
        success: false,
        type: 'error',
        error: '会话不存在',
        sessionId: command.sessionId,
        timestamp: Date.now()
      };
    }

    try {
      switch (command.type) {
        case 'navigate':
          return await this.handleNavigateCommand(session, command);
        case 'click':
          return await this.handleClickCommand(session, command);
        case 'type':
          return await this.handleTypeCommand(session, command);
        case 'scroll':
          return await this.handleScrollCommand(session, command);
        case 'screenshot':
          return await this.handleScreenshotCommand(session, command);
        case 'eval':
          return await this.handleEvalCommand(session, command);
        case 'cookies':
          return await this.handleCookiesCommand(session, command);
        case 'storage':
          return await this.handleStorageCommand(session, command);
        default:
          return {
            success: false,
            type: 'error',
            error: '未知命令类型',
            sessionId: command.sessionId,
            timestamp: Date.now()
          };
      }
    } catch (error) {
      return {
        success: false,
        type: 'error',
        error: error instanceof Error ? error.message : '命令执行失败',
        sessionId: command.sessionId,
        timestamp: Date.now()
      };
    }
  }

  /**
   * 处理导航命令
   */
  private async handleNavigateCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { url, waitUntil = 'networkidle' } = command.data;
    
    try {
      await session.page.goto(url, { waitUntil: waitUntil as any });
      session.status = 'active';
      session.lastActivity = new Date();
      
      return {
        success: true,
        type: 'navigate',
        data: {
          message: '页面导航成功',
          url: session.page.url(),
          title: await session.page.title()
        },
        sessionId: session.id,
        timestamp: Date.now()
      };
    } catch (error) {
      session.status = 'error';
      throw error;
    }
  }

  /**
   * 处理点击命令
   */
  private async handleClickCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { selector, x, y, button = 'left', clickCount = 1 } = command.data;
    
    try {
      if (selector) {
        await session.page.click(selector, { button, clickCount });
      } else if (x !== undefined && y !== undefined) {
        await session.page.mouse.click(x, y, { button, clickCount });
      } else {
        return {
          success: false,
          type: 'click',
          error: '需要提供selector或x,y坐标',
          sessionId: session.id,
          timestamp: Date.now()
        };
      }
      
      session.lastActivity = new Date();
      
      return {
        success: true,
        type: 'click',
        data: { message: '点击操作成功' },
        sessionId: session.id,
        timestamp: Date.now()
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 处理输入命令
   */
  private async handleTypeCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { selector, text, delay = 0 } = command.data;
    
    try {
      if (selector) {
        await session.page.fill(selector, text);
      } else {
        await session.page.keyboard.type(text, { delay });
      }
      
      session.lastActivity = new Date();
      
      return {
        success: true,
        type: 'type',
        data: { message: '输入操作成功' },
        sessionId: session.id,
        timestamp: Date.now()
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 处理滚动命令
   */
  private async handleScrollCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { x, y, selector } = command.data;
    
    try {
      if (selector) {
        await session.page.evaluate((sel) => {
          const element = document.querySelector(sel);
          if (element) {
            element.scrollIntoView();
          }
        }, selector);
      } else {
        await session.page.evaluate(({ scrollX, scrollY }) => {
          window.scrollTo(scrollX, scrollY);
        }, { scrollX: x || 0, scrollY: y || 0 });
      }
      
      session.lastActivity = new Date();
      
      return {
        success: true,
        type: 'scroll',
        data: { message: '滚动操作成功' },
        sessionId: session.id,
        timestamp: Date.now()
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 处理截图命令
   */
  private async handleScreenshotCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { fullPage = false, quality = 80, type = 'jpeg' } = command.data;
    
    try {
      const screenshot = await session.page.screenshot({
        fullPage,
        type: type as 'jpeg' | 'png',
        quality
      });
      
      session.lastActivity = new Date();
      
      return {
        success: true,
        type: 'screenshot',
        data: {
          message: '截图成功',
          screenshot: screenshot.toString('base64'),
          format: 'base64',
          size: screenshot.length
        },
        sessionId: session.id,
        timestamp: Date.now()
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 处理执行脚本命令
   */
  private async handleEvalCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { script, args = [] } = command.data;
    
    try {
      const result = await session.page.evaluate(({ evalScript, evalArgs }) => {
        // 在页面上下文中执行脚本
        const func = new Function('return ' + evalScript)();
        return func(...evalArgs);
      }, { evalScript: script, evalArgs: args });
      
      session.lastActivity = new Date();
      
      return {
        success: true,
        type: 'eval',
        data: {
          message: '脚本执行成功',
          result
        },
        sessionId: session.id,
        timestamp: Date.now()
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 处理cookies命令
   */
  private async handleCookiesCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { action, cookies } = command.data;
    
    try {
      if (action === 'get') {
        const currentCookies = await session.page.context().cookies();
        session.cookies = currentCookies;
        
        return {
          success: true,
          type: 'cookies',
          data: { cookies: currentCookies },
          sessionId: session.id,
          timestamp: Date.now()
        };
      } else if (action === 'set' && cookies) {
        await session.page.context().addCookies(cookies);
        
        return {
          success: true,
          type: 'cookies',
          data: { message: 'Cookies设置成功' },
          sessionId: session.id,
          timestamp: Date.now()
        };
      } else {
        return {
          success: false,
          type: 'cookies',
          error: '不支持的cookies操作',
          sessionId: session.id,
          timestamp: Date.now()
        };
      }
    } catch (error) {
      throw error;
    }
  }

  /**
   * 处理存储命令
   */
  private async handleStorageCommand(session: WebSession, command: WebCommand): Promise<WebResponse> {
    const { action, key, value } = command.data;
    
    try {
      if (action === 'get') {
        const storage = await session.page.evaluate((storageKey) => {
          return localStorage.getItem(storageKey);
        }, key);
        
        return {
          success: true,
          type: 'storage',
          data: { [key]: storage },
          sessionId: session.id,
          timestamp: Date.now()
        };
      } else if (action === 'set') {
        await session.page.evaluate(({ storageKey, storageValue }) => {
          localStorage.setItem(storageKey, storageValue);
        }, { storageKey: key, storageValue: value });
        
        return {
          success: true,
          type: 'storage',
          data: { message: '存储设置成功' },
          sessionId: session.id,
          timestamp: Date.now()
        };
      } else {
        return {
          success: false,
          type: 'storage',
          error: '不支持的存储操作',
          sessionId: session.id,
          timestamp: Date.now()
        };
      }
    } catch (error) {
      throw error;
    }
  }

  /**
   * 导航到URL
   */
  private async navigateToUrl(session: WebSession, url: string): Promise<void> {
    try {
      await session.page.goto(url, { waitUntil: 'networkidle' });
      session.status = 'active';
      session.currentUrl = url;
    } catch (error) {
      session.status = 'error';
      throw error;
    }
  }

  /**
   * 获取会话列表
   */
  private getSessionList(): any[] {
    return Array.from(this.sessions.values()).map(session => ({
      id: session.id,
      platform: session.platform,
      status: session.status,
      currentUrl: session.currentUrl,
      title: session.title,
      lastActivity: session.lastActivity,
      cookiesCount: session.cookies.length,
      storageCount: Object.keys(session.localStorage).length
    }));
  }

  /**
   * 关闭会话
   */
  async closeSession(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (session) {
      await session.page.close();
      this.sessions.delete(sessionId);
      console.log(`WEB会话已关闭: ${sessionId}`);
    }
  }

  /**
   * 启动WEB远程服务
   */
  async start(): Promise<void> {
    console.log(`WEB远程控制服务启动在端口 ${this.config.port}`);
    console.log(`健康检查: http://localhost:${this.config.port}/health`);
    console.log('等待WEB远程控制客户端连接...');
  }

  /**
   * 停止WEB远程服务
   */
  async stop(): Promise<void> {
    // 关闭所有会话
    for (const session of this.sessions.values()) {
      await session.page.close();
    }
    this.sessions.clear();
    
    // 关闭浏览器
    if (this.browser) {
      await this.browser.close();
      this.browser = null;
    }
    
    // 关闭WebSocket服务器
    this.wss.close();
    
    console.log('WEB远程控制服务已停止');
  }

  /**
   * 生成会话ID
   */
  private generateSessionId(): string {
    return `web-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }
}

// 导出默认配置
export const defaultWebRemoteConfig: WebRemoteConfig = {
  port: 8082,
  headless: true,
  viewport: { width: 1920, height: 1080 },
  userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
};

// 导出单例实例
export const webRemoteService = new WebRemoteService(defaultWebRemoteConfig);