/* eslint-disable */
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
import CryptoJS from 'crypto-js';

export interface EncryptedMessage {
  id: string;
  sender: string;
  ciphertext: string;
  timestamp: number;
}

export interface DecryptedMessage {
  id: string;
  sender: string;
  content: string;
  timestamp: number;
  status: string;
}

/**
 * XCUTelepathyMatrix FASE 2:
 * Telah berevolusi meninggalkan NodeJS, Yjs, dan WebSockets usang.
 * Menggunakan arsitektur WebTransport Datagrams yang menembak langsung ke Rust Engine (Port 8443).
 */
export class XCUTelepathyMatrix {
  private roomName: string;
  private secretKey: string;
  private transport: any = null; // WebTransport instance
  private isActive: boolean = false;
  private participantId: number;
  private username: string = "";
  
  public onMessagesUpdate: ((messages: DecryptedMessage[]) => void) | null = null;
  public onTypingUpdate: ((typingUsers: Record<string, number>) => void) | null = null;
  public onQuantumResonance: ((senderId: number, type: string) => void) | null = null;
  public onSovereignSignal: ((command: string, targetId?: number) => void) | null = null;

  // Local state untuk dirender
  private messages: DecryptedMessage[] = [];
  private typingState: Record<string, number> = {};

  constructor(roomName: string, secretKey: string = 'QUANTUM-X-SECRET-256') {
    this.roomName = roomName;
    this.secretKey = secretKey;
    this.participantId = Math.floor(Math.random() * 65534) + 1;
  }

  public async ignite(serverUrl: string, username: string) {
    this.username = username;
    this.isActive = true;
    
    try {
      // 1. Ekstrak host dari serverUrl
      let host = window.location.hostname;
      if (serverUrl && serverUrl !== "/") {
          const urlObj = new URL(serverUrl);
          host = urlObj.hostname;
      }
      
      const secureProto = window.location.protocol;
      const wtUrl = `${secureProto}//${host}:8443/neural-link/${this.roomName}`;
      console.log("[XTM] Menginisialisasi WebTransport ke:", wtUrl);

      // 2. Setup WebTransport
      // Gunakan any cast karena WebTransport mungkin belum diakui di semua tsconfig
      const WT = (window as any).WebTransport;
      if (!WT) {
          throw new Error("WebTransport tidak didukung di browser ini!");
      }

      this.transport = new WT(wtUrl);
      await this.transport.ready;
      console.log("[XTM] Pipa WebTransport Kuantum TERHUBUNG!");

      // 3. Mulai Membaca Datagrams
      this.readDatagrams();

    } catch (e) {
      console.error("[XTM] Ignition Failed:", e);
      // Fallback: Jika WebTransport diblokir firewall, XTM akan mengaktifkan SSE Relay (TBD)
    }
  }

  private async readDatagrams() {
      if (!this.transport || !this.transport.datagrams) return;
      
      try {
          const reader = this.transport.datagrams.readable.getReader();
          while (this.isActive) {
              const { value, done } = await reader.read();
              if (done) break;
              
              if (value && value.length >= 8) {
                  const type = value[0];
                  // byte 2-3 = participantId pengirim
                  const senderId = new DataView(value.buffer).getUint16(2, true);
                  
                  if (senderId === this.participantId) continue;

                  const payload = value.slice(8);
                  
                  if (type === 7) { // 7 = Chat Text
                      this.decryptAndPush(payload);
                  } else if (type === 8) { // 8 = Telepathic Resonance (Typing)
                      // Mendekripsi siapa yang mengetik
                      this.handleTypingResonance(payload);
                  } else if (type === 9) { // 9 = PKEPX Resonance (Emoji)
                      this.handleQuantumResonance(payload, senderId);
                  } else if (type === 10) { // 10 = PKEPX Sovereign Command
                      this.handleSovereignCommand(payload);
                  }
              }
          }
      } catch (e) {
          if (this.isActive) console.error("[XTM] Datagram Reader terputus:", e);
      }
  }

  private async decryptAndPush(payload: Uint8Array) {
      try {
          // Convert Uint8Array to WordArray
          const wordArr = CryptoJS.lib.WordArray.create(payload as any);
          const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
          
          const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
          const originalText = bytes.toString(CryptoJS.enc.Utf8);
          
          if (originalText) {
              const parsed = JSON.parse(originalText);
              this.messages.push({
                  id: Math.random().toString(),
                  sender: parsed.sender,
                  content: parsed.text,
                  timestamp: parsed.timestamp,
                  status: 'delivered'
              });
              
              if (this.onMessagesUpdate) {
                  this.onMessagesUpdate([...this.messages]);
              }
          }
      } catch (e) {
          console.error("Gagal dekripsi pesan XTM", e);
      }
  }

  private async handleTypingResonance(payload: Uint8Array) {
      try {
          const wordArr = CryptoJS.lib.WordArray.create(payload as any);
          const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
          const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
          const name = bytes.toString(CryptoJS.enc.Utf8);
          
          if (name) {
              this.typingState[name] = Date.now();
              if (this.onTypingUpdate) this.onTypingUpdate({...this.typingState});
              
              setTimeout(() => {
                  delete this.typingState[name];
                  if (this.onTypingUpdate) this.onTypingUpdate({...this.typingState});
              }, 3000);
          }
      } catch(e) {}
  }

  // =====================================
  // PKEPX ZOOM-KILLER: JUMPA CHAT PORT
  // =====================================

  private async handleQuantumResonance(payload: Uint8Array, senderId: number) {
      try {
          const wordArr = CryptoJS.lib.WordArray.create(payload as any);
          const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
          const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
          const reactionType = bytes.toString(CryptoJS.enc.Utf8);
          if (reactionType && this.onQuantumResonance) {
              this.onQuantumResonance(senderId, reactionType);
          }
      } catch(e) {}
  }

  private async handleSovereignCommand(payload: Uint8Array) {
      try {
          const wordArr = CryptoJS.lib.WordArray.create(payload as any);
          const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
          const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
          const cmdStr = bytes.toString(CryptoJS.enc.Utf8);
          if (cmdStr && this.onSovereignSignal) {
              const cmd = JSON.parse(cmdStr);
              this.onSovereignSignal(cmd.command, cmd.targetId);
          }
      } catch(e) {}
  }

  public async emitResonance(reactionType: string) {
      if (!this.transport || !this.transport.datagrams) return;
      
      const ciphertext = CryptoJS.AES.encrypt(reactionType, this.secretKey).toString();
      const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
      const encPayload = new Uint8Array(encWordArr.sigBytes);
      for (let i = 0; i < encWordArr.sigBytes; i++) {
         encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
      }
      
      const header = new Uint8Array(8);
      header[0] = 9; // Tipe 9 = Resonance
      new DataView(header.buffer).setUint16(2, this.participantId, true);
      
      const fullPacket = new Uint8Array(8 + encPayload.length);
      fullPacket.set(header, 0);
      fullPacket.set(encPayload, 8);
      
      let writer: any = null;
      try {
          writer = this.transport.datagrams.writable.getWriter();
          await writer.write(fullPacket);
          if (this.onQuantumResonance) this.onQuantumResonance(this.participantId, reactionType);
      } catch (e) {} finally {
          if (writer) writer.releaseLock();
      }
  }

  public async broadcastSovereignSignal(command: string, targetId?: number) {
      if (!this.transport || !this.transport.datagrams) return;
      
      const payloadStr = JSON.stringify({ command, targetId });
      const ciphertext = CryptoJS.AES.encrypt(payloadStr, this.secretKey).toString();
      const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
      const encPayload = new Uint8Array(encWordArr.sigBytes);
      for (let i = 0; i < encWordArr.sigBytes; i++) {
         encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
      }
      
      const header = new Uint8Array(8);
      header[0] = 10; // Tipe 10 = Sovereign
      new DataView(header.buffer).setUint16(2, this.participantId, true);
      
      const fullPacket = new Uint8Array(8 + encPayload.length);
      fullPacket.set(header, 0);
      fullPacket.set(encPayload, 8);
      
      let writer: any = null;
      try {
          writer = this.transport.datagrams.writable.getWriter();
          await writer.write(fullPacket);
      } catch (e) {} finally {
          if (writer) writer.releaseLock();
      }
  }

  // Encrypt and send
  public async sendMessage(sender: string, content: string) {
    if (!this.transport || !this.transport.datagrams) {
        // Fallback simpan ke local buffer jika belum konek
        this.messages.push({
            id: Math.random().toString(),
            sender,
            content,
            timestamp: Date.now(),
            status: 'failed_offline'
        });
        if (this.onMessagesUpdate) this.onMessagesUpdate([...this.messages]);
        return;
    }

    const payloadStr = JSON.stringify({ sender, text: content, timestamp: Date.now() });
    
    // E2EE: AES Encryption
    const ciphertext = CryptoJS.AES.encrypt(payloadStr, this.secretKey).toString();
    const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
    // Convert WordArray to Uint8Array
    const encPayload = new Uint8Array(encWordArr.sigBytes);
    for (let i = 0; i < encWordArr.sigBytes; i++) {
        encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
    }
    
    // Header
    const header = new Uint8Array(8);
    header[0] = 7; // Tipe 7 = Text Message
    header[1] = 0;
    new DataView(header.buffer).setUint16(2, this.participantId, true);

    const fullPacket = new Uint8Array(8 + encPayload.length);
    fullPacket.set(header, 0);
    fullPacket.set(encPayload, 8);

    let writer: any = null;
    try {
        writer = this.transport.datagrams.writable.getWriter();
        await writer.write(fullPacket);
        
        // Optimistic UI Update
        this.messages.push({
            id: Math.random().toString(),
            sender,
            content,
            timestamp: Date.now(),
            status: 'delivered'
        });
        if (this.onMessagesUpdate) this.onMessagesUpdate([...this.messages]);
    } catch (e) {
        console.error("Gagal mengirim pesan Kuantum:", e);
    } finally {
        if (writer) writer.releaseLock();
    }
  }

  public async setTyping(username: string, charCount: number) {
     if (!this.transport || !this.transport.datagrams) return;
     
     const ciphertext = CryptoJS.AES.encrypt(username, this.secretKey).toString();
     const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
     const encPayload = new Uint8Array(encWordArr.sigBytes);
     for (let i = 0; i < encWordArr.sigBytes; i++) {
        encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
     }
     
     const header = new Uint8Array(8);
     header[0] = 8; // Tipe 8 = Typing
     new DataView(header.buffer).setUint16(2, this.participantId, true);
     
     const fullPacket = new Uint8Array(8 + encPayload.length);
     fullPacket.set(header, 0);
     fullPacket.set(encPayload, 8);
     
     let writer: any = null;
     try {
         writer = this.transport.datagrams.writable.getWriter();
         await writer.write(fullPacket);
     } catch (e) {} finally {
         if (writer) writer.releaseLock();
     }
  }

  public shutdown() {
    this.isActive = false;
    if (this.transport) {
        try { this.transport.close(); } catch(e){}
    }
  }
}
