import { Component, OnDestroy, OnInit } from '@angular/core';
import { EstimatedInstanceRevenueService } from '@fleio-api/reports/estimated-instance-revenue.service';
import { ConfigService } from '@shared/config/config.service';
import { IIcon } from '@shared/ui/common/interfaces/icon';
import { Subscription } from 'rxjs';
import { RegionsApiService } from '@fleio-api/openstack/region/regions-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { Router } from '@angular/router';

export interface IEstimatedInstanceRevenueReport {
  per_region_report: {
    [region: string]: {
      base_revenue: number;
      base_revenue_currency: string;
      extras_revenue: number;
      total_revenue: number;
      instance_count: number;
      per_flavor_report: {
        [flavor_name: string]: {
          base_revenue: number;
          base_revenue_currency: string;
          extras_revenue: number;
          total_revenue: number;
          instance_count: number;
        };
      };
      flavor_names: Array<string>;
    };
  };
  total_instances: number;
  total_base_revenue: number;
  total_extras_revenue: number;
  total_revenue: number;
  revenue_currency: string;
}


@Component({
  selector: 'app-estimated-instance-revenue',
  templateUrl: './estimated-instance-revenue.component.html',
  styleUrls: ['./estimated-instance-revenue.component.scss']
})
export class EstimatedInstanceRevenueComponent implements OnInit, OnDestroy {
  report: IEstimatedInstanceRevenueReport;
  regionNames: Array<string> = [];
  regionReports = {};
  loadingRegionReports = 0;
  loadingRegionName = null;
  loading = false;
  getRegionReportSubscription: Subscription;
  combineReportSubscription: Subscription;

  baseInfoIcon = {
    name: 'info',
    fontSize: '16px',
    height: '17px',
    marginLeft: '5px',
    verticalAlign: 'middle',
  } as IIcon;

  instanceCountIcon = Object.assign({}, this.baseInfoIcon);
  baseRevenueHeaderIcon = Object.assign({}, this.baseInfoIcon);
  extrasRevenueHeaderIcon = Object.assign({}, this.baseInfoIcon);
  totalRevenueHeaderIcon = Object.assign({}, this.baseInfoIcon);

  hideZeroInstancesFlavors = true;

  constructor(
    private estimatedInstanceRevenueService: EstimatedInstanceRevenueService,
    private notificationsService: NotificationService,
    private regionsApiService: RegionsApiService,
    private router: Router,
    public config: ConfigService,
  ) { }

  ngOnInit(): void {
    this.instanceCountIcon.tooltip = $localize`Number of instances that are currently active`;
    this.baseRevenueHeaderIcon.tooltip = $localize`Instance pricing rule revenue`;
    this.extrasRevenueHeaderIcon.tooltip = $localize`Instance extras revenue (image snapshots & backups, attached volumes, IPs, floating IPs`;
    this.totalRevenueHeaderIcon.tooltip = $localize`Sum of base and extras revenue`;

    this.loading = true;
    this.regionsApiService.list().subscribe(regionResponse => {
      for (const region of regionResponse.objects) {
        this.regionNames.push(region.id.toString());
      }
      if (this.regionNames.length) {
        // process the first region in list
        this.retrieveRegionReport(this.regionNames[0]);
      } else {
        this.notificationsService.showMessage($localize`No regions to build report for.`);
        this.router.navigateByUrl(this.config.getPanelUrl('utilities/reports')).then(() => {});
      }
    });
  }

  allRegionsProcessed() {
    return this.regionNames.length === Object.keys(this.regionReports).length;
  }

  combineRegionReports() {
    this.combineReportSubscription = this.estimatedInstanceRevenueService.combineRegionReports(
      JSON.stringify(this.regionReports)
    ).subscribe({
      next: (response) => {
        this.report = response.report;
        // override regionNames list with sorted one from final report
        this.regionNames = Object.keys(this.report.per_region_report);
        this.loading = false;
      },
      error: () => {
        // error will be handled by interceptor
        this.router.navigateByUrl(this.config.getPanelUrl('utilities/reports'));
      }
    });
  }

  retrieveRegionReport(regionName: string) {
    this.loadingRegionReports += 1;
    this.loadingRegionName = regionName;
    this.getRegionReportSubscription = this.estimatedInstanceRevenueService.getReportForRegion(
      regionName,
    ).subscribe({
      next: (value) => {
        this.regionReports[regionName] = value.report;
        if (!this.allRegionsProcessed()) {
          // if not all regions were processed, get the report for remaining unprocessed regions
          const nextRegion = this.regionNames.find(
            region => !Object.keys(this.regionReports).includes(region)
          );
          this.retrieveRegionReport(nextRegion);
        } else {
          // all regions processed, combine the generated reports
          this.combineRegionReports();
        }
      },
      error: () => {
        // error will be handled by interceptor
        this.router.navigateByUrl(this.config.getPanelUrl('utilities/reports'));
      }
    });
  }

  htmlToCSV() {
    const data = [];
    const table = document.getElementById('report-table');
    const clonedTable = table.cloneNode(true) as any;
    const infoElements = clonedTable.getElementsByClassName('info-elem');
    while (infoElements.length) {
      infoElements[infoElements.length - 1].remove();
    }
    const rows = clonedTable.querySelectorAll('tr');
    // eslint-disable-next-line @typescript-eslint/prefer-for-of
    for (let i = 0; i < rows.length; i++) {
      const tr = rows[i];
      const row = []; const cols = tr.querySelectorAll('td, th');
      const colsArray = Array.from(cols) as any;
      if (tr.classList.contains('report-headers')) {
        colsArray.splice(1, 0, {innerText: 'Flavors'}); // add flavor column
        colsArray[0].innerText = 'Regions';
        colsArray.splice(3, 0, {innerText: 'Instance count/flavor'});
        colsArray[2].innerText = 'Instance count/region';
        colsArray.splice(5, 0, {innerText: 'Base revenue/flavor'});
        colsArray[4].innerText = 'Base revenue/region';
        colsArray.splice(7, 0, {innerText: 'Extras revenue/flavor'});
        colsArray[6].innerText = 'Extras revenue/region';
        colsArray.splice(9, 0, {innerText: 'Total revenue/flavor'});
        colsArray[8].innerText = 'Total revenue/region';
      } else if (tr.classList.contains('flavor-row')) {
        let columnIndex = 1;
        while (columnIndex < 10) {
          colsArray.splice(columnIndex, 0, {innerText: colsArray[columnIndex - 1].innerText}); // add flavor column
          colsArray[columnIndex - 1].innerText = '';
          columnIndex += 2;
        }
      } else if (tr.classList.contains('region-row')) {
        let columnIndex = 1;
        while (columnIndex < 10) {
          colsArray.splice(columnIndex, 0, {innerText: ''}); // add flavor column
          columnIndex += 2;
        }
      } else if (tr.classList.contains('totals-row')) {
        let columnIndex = 1;
        while (columnIndex < 10) {
          if (columnIndex === 1) {
            colsArray.splice(columnIndex, 0, {innerText: ''}); // add flavor column
          } else {
            colsArray.splice(columnIndex, 0, {innerText: colsArray[columnIndex - 1].innerText});
          }
          columnIndex += 2;
        }
      }
      // eslint-disable-next-line @typescript-eslint/prefer-for-of
      for (let j = 0; j < colsArray.length; j++) {
          // @ts-ignore
          row.push(`"${colsArray[j].innerText}"`);
      }
      data.push(row.join(','));
    }
    this.downloadCSVFile(data.join('\n'));
  }

  downloadCSVFile(csv) {
    const csv_file = new Blob([csv], {type: 'text/csv'});
    const download_link = document.createElement('a');
    download_link.download = 'report';
    download_link.href = window.URL.createObjectURL(csv_file);
    download_link.style.display = 'none';
    document.body.appendChild(download_link);
    download_link.click();
  }

  printReport() {
    const table = document.getElementById('report-table');
    const clonedTable = table.cloneNode(true) as any;
    clonedTable.setAttribute('border', '1');
    const infoElements = clonedTable.getElementsByClassName('info-elem');
    while (infoElements.length) {
      infoElements[infoElements.length - 1].remove();
    }
    const newWin = window.open('');
    newWin.document.write(clonedTable.outerHTML);
    newWin.print();
  }

  ngOnDestroy() {
    if (this.getRegionReportSubscription) {
      // this will stop getting further reports for other regions
      // in the background if user navigates somewhere else
      this.getRegionReportSubscription.unsubscribe();
      this.getRegionReportSubscription = null;
    }
    if (this.combineReportSubscription) {
      this.combineReportSubscription.unsubscribe();
      this.combineReportSubscription = null;
    }
  }

}
