import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { DeployService } from './deploy.service';
import { environment } from '../environments/environment';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  // Environment config
  env = environment;

  // Form fields
  apiEndpoint = '';
  username = '';
  password = '';
  organization = '';
  space = '';
  appName = '';
  skipSsl = false;
  jarFile: File | null = null;
  manifestFile: File | null = null;

  // Upload state
  uploading = false;
  uploadProgress = 0;
  currentStep = '';
  logs: string[] = [];
  logsExpanded = environment.defaultLogsExpanded;
  deploymentStatus = '';
  sessionId = '';

  constructor(private deployService: DeployService) {}

  ngOnInit(): void {
    // Auto-populate form fields from environment.local.ts (development only)
    const formDefaults = environment.formDefaults as any;
    if (formDefaults && formDefaults.enabled) {
      this.apiEndpoint = formDefaults.apiEndpoint || '';
      this.username = formDefaults.username || '';
      this.password = formDefaults.password || '';
      this.organization = formDefaults.organization || '';
      this.space = formDefaults.space || '';
      this.appName = formDefaults.appName || '';
      this.skipSsl = formDefaults.skipSslValidation || false;

      console.log('Form auto-populated from environment.local.ts');
    }
  }

  onJarFileChange(event: any) {
    this.jarFile = event.target.files[0];
  }

  onManifestFileChange(event: any) {
    this.manifestFile = event.target.files[0];
  }

  addLog(message: string) {
    const timestamp = new Date().toLocaleTimeString();
    this.logs.push(`[${timestamp}] ${message}`);
  }

  async deploy() {
    if (!this.jarFile || !this.manifestFile) {
      alert('Please select both JAR and Manifest files');
      return;
    }

    this.uploading = true;
    this.uploadProgress = 0;
    this.logs = [];
    this.deploymentStatus = '';

    try {
      // Step 1: Initialize upload session
      this.currentStep = 'Initializing upload session...';
      this.addLog('Step 1/5: Initializing upload session');

      const config = {
        apiEndpoint: this.apiEndpoint,
        username: this.username,
        password: this.password,
        organization: this.organization,
        space: this.space,
        appName: this.appName,
        skipSslValidation: this.skipSsl
      };

      const initResponse = await this.deployService.initUpload(config);
      this.sessionId = initResponse.uploadSessionId;
      this.addLog(`✓ Session created: ${this.sessionId}`);
      this.uploadProgress = 10;

      // Step 2: Upload JAR file
      this.currentStep = 'Uploading JAR file...';
      this.addLog(`Step 2/5: Uploading JAR file (${(this.jarFile.size / 1024 / 1024).toFixed(2)}MB)`);

      await this.uploadFileInChunks(this.jarFile, 'jarFile', 10, 50);
      this.addLog('✓ JAR file upload completed');

      // Step 3: Upload manifest file
      this.currentStep = 'Uploading manifest file...';
      this.addLog('Step 3/5: Uploading manifest file');

      await this.uploadFileInChunks(this.manifestFile, 'manifest', 50, 60);
      this.addLog('✓ Manifest file upload completed');

      // Step 4: Finalize and start deployment
      this.currentStep = 'Starting deployment...';
      this.addLog('Step 4/5: Starting async deployment');

      const finalizeResponse = await this.deployService.finalizeUpload(this.sessionId);
      this.addLog(`✓ Deployment started (Status: ${finalizeResponse.status})`);
      this.uploadProgress = 70;

      // Step 5: Poll deployment status
      this.currentStep = 'Deploying application...';
      this.addLog('Step 5/5: Polling deployment status');

      await this.pollDeploymentStatus();

    } catch (error: any) {
      this.addLog(`✗ ERROR: ${error.message || error}`);
      this.currentStep = 'Deployment failed';
      this.deploymentStatus = 'FAILED';
      this.uploading = false;
    }
  }

  async uploadFileInChunks(file: File, fileType: string, startProgress: number, endProgress: number) {
    const CHUNK_SIZE = environment.chunkSize;
    const totalChunks = Math.ceil(file.size / CHUNK_SIZE);

    for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
      const start = chunkIndex * CHUNK_SIZE;
      const end = Math.min(start + CHUNK_SIZE, file.size);
      const chunk = file.slice(start, end);

      // Convert chunk to base64
      const base64Chunk = await this.fileToBase64(chunk);

      await this.deployService.uploadChunk(
        this.sessionId,
        fileType,
        file.name,
        chunkIndex,
        totalChunks,
        base64Chunk
      );

      const progress = startProgress + ((chunkIndex + 1) / totalChunks) * (endProgress - startProgress);
      this.uploadProgress = Math.round(progress);
      this.addLog(`  Chunk ${chunkIndex + 1}/${totalChunks} uploaded`);
    }
  }

  async fileToBase64(blob: Blob): Promise<string> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => {
        const base64 = (reader.result as string).split(',')[1];
        resolve(base64);
      };
      reader.onerror = reject;
      reader.readAsDataURL(blob);
    });
  }

  async pollDeploymentStatus() {
    const maxAttempts = environment.maxPollAttempts;
    let attempts = 0;

    while (attempts < maxAttempts) {
      await new Promise(resolve => setTimeout(resolve, environment.pollInterval));

      const status = await this.deployService.getDeploymentStatus(this.sessionId);
      this.deploymentStatus = status.status;

      const progressPercent = 70 + (status.progress || 0) * 0.3;
      this.uploadProgress = Math.round(progressPercent);

      this.addLog(`  Status: ${status.status} - ${status.message || ''}`);

      if (status.status === 'COMPLETED') {
        this.currentStep = 'Deployment completed successfully!';
        this.uploadProgress = 100;
        this.uploading = false;
        this.addLog('✓ Deployment completed successfully!');
        return;
      }

      if (status.status === 'FAILED') {
        this.currentStep = 'Deployment failed';
        this.uploading = false;
        this.addLog(`✗ Deployment failed: ${status.message}`);
        if (status.error) {
          this.addLog(`  Error: ${status.error}`);
        }
        throw new Error('Deployment failed');
      }

      attempts++;
    }

    throw new Error('Deployment timeout after 10 minutes');
  }

  toggleLogs() {
    this.logsExpanded = !this.logsExpanded;
  }

  clearForm() {
    this.apiEndpoint = '';
    this.username = '';
    this.password = '';
    this.organization = '';
    this.space = '';
    this.appName = '';
    this.skipSsl = false;
    this.jarFile = null;
    this.manifestFile = null;
    this.logs = [];
    this.uploadProgress = 0;
    this.currentStep = '';
    this.deploymentStatus = '';
  }
}
