import { Component, OnInit } from '@angular/core';
import { DetailsComponentBase } from '@objects-view/details-component-base';
import { IInvoiceModel } from '@fleio-api/billing/model/invoice.model';
import { ConfigService } from '@shared/config/config.service';
import { ITransactionModel } from '@fleio-api/billing/model/transaction.model';
import { RefreshService } from '@shared/ui-api/refresh.service';
import { TransactionsApiService } from '@fleio-api/billing/transaction/transaction-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { FleioId } from '@fleio-api/base-model/base-fleio-object.model';
import { InvoicesApiService } from '@fleio-api/billing/invoices/invoices-api.service';
import { IJournalEntryModel } from '@fleio-api/billing/model/journal-entry.model';
import { CurrencyFormatterPipe } from '@shared/ui/common/pipes/currency-formatter.pipe';
import { DateFormatterPipe } from '@shared/ui/common/pipes/date-formatter.pipe';

@Component({
  selector: 'app-invoice-details-overview',
  templateUrl: './invoice-details-overview.component.html',
  styleUrls: ['./invoice-details-overview.component.scss']
})
export class InvoiceDetailsOverviewComponent extends DetailsComponentBase<IInvoiceModel> implements OnInit {
  private datePipe: DateFormatterPipe;
  private currencyPipe: CurrencyFormatterPipe;
  downloadPdfUrl: string;
  displayedJournalColumns: string[] = [
    'date_added', 'source_info', 'destination_info', 'destination_amount'
  ];
  itemLinks: { [itemId: number]: string };
  selectedItems = {};
  canSplitInvoice = {
    value: false,
    reason: $localize`Select items to\nsplit into a new invoice`,
  };
  isUpgradeInvoice = false;

  regeneratePDFInvoicePermissionTooltip = $localize`Missing permission to\nregenerate PDF invoice`;
  showRegeneratePDF: boolean = false;

  downloadInvoiceTooltip = $localize`Missing permission to\ndownload invoice`;
  downloadInvoiceEnabled = false;

  constructor(
    public config: ConfigService,
    private refreshService: RefreshService,
    private transactionApi: TransactionsApiService,
    private notificationService: NotificationService,
    private invoicesApi: InvoicesApiService,
  ) {
    super();
    this.datePipe = new DateFormatterPipe(this.config);
    this.currencyPipe = new CurrencyFormatterPipe(this.config);
  }

  public get object(): IInvoiceModel {
    if (this.objectController) {
      const invoice = Object.assign(this.objectController.object) as IInvoiceModel;
      const distinctClients = invoice.items.reduce(
        (clients, item, currentIndex, items) => {
          clients[item.client_name] = item.client_name;
          return clients;
        }, {});

      invoice.displayClient = Object.keys(distinctClients).length > 1;

      this.itemLinks = {};
      for (const item of invoice.items) {
        if (item.item_type === 'serviceUpgrade') {
          this.isUpgradeInvoice = true;
        }
        if (this.authSvc.feature('ui.staff') || item.has_service_url) {
          if (item.domain_id) {
            this.itemLinks[item.id] = this.config.getPanelUrl('domains/', item.service);
          } else {
            if (item.service) {
              this.itemLinks[item.id] = this.config.getPanelUrl('billing/services/', item.service);
            }
          }
        }
      }
      return invoice;
    }
    return null;
  }


  ngOnInit() {
    super.ngOnInit();
    if (!this.authSvc.feature('ui.billing.invoices.simple-journal')) {
      this.displayedJournalColumns.push('(actions)');
    }
    if (this.object) {
      this.downloadPdfUrl = this.config.getPanelApiUrl(
        `billing/invoices/${this.object.id}/download?content_type=pdf`
      );
      this.downloadInvoiceEnabled = this.objectController.permissions['invoices.download'];
      if (this.downloadInvoiceEnabled) {
        this.downloadInvoiceEnabled = ['generated', 'on demand'].includes(this.object.pdf_invoice_status);
        if (!this.downloadInvoiceEnabled) {
          switch (this.object.pdf_invoice_status) {
            case 'generating':
              this.downloadInvoiceTooltip = $localize`PDF invoice is still generating,\ntry again later`;
              break;
            case 'error':
              if (this.authSvc.feature('ui.staff')) {
                this.downloadInvoiceTooltip = $localize`Error generating PDF invoice,\ncheck logs for details.`;
              } else {
                this.downloadInvoiceTooltip = $localize`Error generating PDF invoice,\nplease contact support.`;
              }
              break;
            default:
              this.downloadInvoiceTooltip = $localize`Cannot download PDF invoice,\nplease contact support.`;
              break;
          }
        }
        this.showRegeneratePDF = this.authSvc.feature('ui.staff') && this.object.pdf_invoice_status !== 'on demand';
      }
    }
  }

  deleteTransaction(transaction: ITransactionModel) {
    this.transactionApi.journalEntries(transaction.id).subscribe(response => {
      let htmlMessage = null;
      const journalEntries: Array<IJournalEntryModel> = response.data;
      if (journalEntries && journalEntries.length) {
        if (journalEntries.length > 1) {
          htmlMessage = '<p class="fl-important-text">' + $localize`This also deletes multiple journal entries:` + '</p>';
        } else {
          htmlMessage = '<p>' + $localize`This also deletes the journal entry:` + '</p>';
        }
        for (const journalEntry of journalEntries) {
          const amount = this.currencyPipe.transform(
            journalEntry.destination_amount, journalEntry.destination_currency, this.config.authService.currencyDisplayMode
          );
          htmlMessage += '<p>' + `${this.datePipe.transform(journalEntry.date_added)} - ${journalEntry.source_info.name} - ${journalEntry.destination_info.name} - ${amount}` + '</p>';
        }
      }
      this.notificationService.confirmDialog(
        {
          title: $localize`Delete transaction`,
          message: $localize`Are you sure you want to delete transaction?`,
          htmlMessage,
          noButtonName: $localize`Cancel`,
          yesButtonName: $localize`Delete`,
        }
      ).subscribe(result => {
        if (result?.button === 'yes') {
          this.refreshService.resetPageChanged();
          this.transactionApi.delete(transaction.id).subscribe(() => {
            this.refreshService.refresh(null, true);
          });
        }
      });
    });
  }

  selectedInvoiceItem(id: FleioId) {
    this.selectedItems[id] = !this.selectedItems[id];
    let selectedCount = 0;
    this.canSplitInvoice = {
      value: false,
      reason: $localize`Select items to\nsplit into a new invoice`,
    };
    for (const itemId in this.selectedItems) {
      if (this.selectedItems.hasOwnProperty(itemId)) {
        if (this.selectedItems[itemId] === true) {
          this.canSplitInvoice = {
            value: true,
            reason: '',
          };
          selectedCount += 1;
        }
      }
    }
    if (this.object.items && selectedCount === this.object.items.length) {
      this.canSplitInvoice = {
        value: false,
        reason: $localize`Cannot split all items.`,
      };
    }
  }

  getItemsToSplit() {
    const itemsToSplit = [];
    for (const id in this.selectedItems) {
      if (this.selectedItems.hasOwnProperty(id)) {
        if (this.selectedItems[id] === true) {
          itemsToSplit.push(id);
        }
      }
    }
    return itemsToSplit;
  }

  splitInvoice() {
    const itemsToSplit = this.getItemsToSplit();
    this.invoicesApi.splitOptions(this.object.id, itemsToSplit).subscribe({
      next: (response) => {
        let importantMessage = null;
        let buttonName = $localize`Split`;
        if (response.partially_paid) {
          if (!response.can_split) {
            importantMessage = $localize`You cannot split these items since the existing payment will exceed the resulting current invoice total.`;
            buttonName = $localize`Ok`;
          } else {
            if (response.paid_after_split) {
              importantMessage = $localize`The existing partial payment will turn current invoice into PAID.`;
            } else {
              importantMessage = $localize`The partial payment will remain associated with current invoice.`;
            }
          }
        }
        const dialogResult$ = this.notificationService.confirmDialog({
          title: $localize`Split invoice?`,
          message: $localize`Are you sure you want to split the selected invoice items?`,
          secondaryMessage: $localize`Splitting will remove selected items from this invoice and will create a new invoice with selected items.`,
          importantMessage,
          yesButtonName: buttonName,
          hideNoButton: response.partially_paid && !response.can_split,
        });
        dialogResult$.subscribe(dialogResult => {
          if (dialogResult?.button === 'yes') {
            if (response.partially_paid && !response.can_split) {
              return;
            }
            this.invoicesApi.split(this.object.id, itemsToSplit).subscribe(() => {
              // split success, re-init relevant values
              this.selectedItems = {};
              this.canSplitInvoice = {
                value: false,
                reason: $localize`Select items to\nsplit into a new invoice`,
              };
              this.refreshService.refresh();
            }, (error) => {
              if (error?.error?.detail) {
                this.notificationService.showMessage(error.error.detail);
              } else {
                this.notificationService.showMessage($localize`Failed to split invoice.`);
              }
            });
          }
        });
      }, error: (error) => {
        if (error?.error?.items) {
          this.notificationService.showMessage(error?.error?.items);
        } else {
          this.notificationService.showMessage($localize`Failed to split invoice.`);
        }
      }
    });
  }

  downloadPDF() {
    this.authSvc.generateOtpToken().subscribe(token => {
      window.location.href = this.downloadPdfUrl + `&fleio-token=${token}`;
    });
  }

  regeneratePDF() {
    this.invoicesApi.regeneratePDF(this.object.id).subscribe({
      next: (response) => {
        this.notificationService.showMessage(response.detail);
        this.refreshService.refresh();
      }, error: (error) => {
        if (error?.error?.detail) {
          this.notificationService.showMessage(error.error.detail);
        } else {
          this.notificationService.showMessage($localize`Failed regenerate PDF invoice, check logs for details`);
        }
      }
    });
  }
}
