import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { DialogsModule } from '@progress/kendo-angular-dialog';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { InputsModule } from '@progress/kendo-angular-inputs';
import { ExpenseApiService } from '../../services/expense-api.service';
import { ExpenseDto } from '../../models/expense.model';
import { EXPENSE_REJECT_REASON_OPTIONS } from '../../../../shared/i18n/option-lists';

/**
 * Approval review dialog: shows the full expense detail and a receipt preview side by side,
 * then lets a reviewer Approve or Reject (with a templated or free-text reason). The parent
 * performs the actual api.approve / api.reject call from the emitted events.
 */
@Component({
  selector: 'app-expense-review-dialog',
  standalone: true,
  imports: [CommonModule, FormsModule, ButtonsModule, DialogsModule, DropDownsModule, InputsModule],
  templateUrl: './expense-review-dialog.component.html',
})
export class ExpenseReviewDialogComponent implements OnInit, OnDestroy {
  /** Expense to review; the full detail (with lines) is fetched on open. */
  @Input() expenseId!: number;
  @Output() approve = new EventEmitter<void>();
  @Output() reject = new EventEmitter<string>();   // emits the composed reviewNotes
  @Output() cancel = new EventEmitter<void>();

  expense: ExpenseDto | null = null;
  loading = true;

  readonly rejectReasons = EXPENSE_REJECT_REASON_OPTIONS;
  /** false = the Approve/Reject choice; true = the reject reason is being collected. */
  rejecting = false;
  rejectReason: string | null = null;
  rejectOther = '';

  // ── Receipt preview (mirrors expense-form-dialog) ───────────────────────
  receiptImageUrl: string | null = null;
  receiptPdfUrl: SafeResourceUrl | null = null;
  private receiptObjectUrl: string | null = null;
  receiptZoom = 1;
  readonly minZoom = 0.5;
  readonly maxZoom = 5;

  get showReceiptPanel(): boolean { return !!(this.receiptImageUrl || this.receiptPdfUrl); }

  zoomIn(): void { this.receiptZoom = Math.min(this.maxZoom, +(this.receiptZoom + 0.25).toFixed(2)); }
  zoomOut(): void { this.receiptZoom = Math.max(this.minZoom, +(this.receiptZoom - 0.25).toFixed(2)); }
  resetZoom(): void { this.receiptZoom = 1; }

  constructor(private api: ExpenseApiService, private sanitizer: DomSanitizer) {}

  ngOnInit(): void {
    this.api.getById(this.expenseId).subscribe({
      next: dto => {
        this.expense = dto;
        this.loading = false;
        if (dto.hasReceipt) {
          this.api.downloadReceipt(dto.id).subscribe(blob => this.setPreview(blob, blob.type));
        }
      },
      error: () => { this.loading = false; },
    });
  }

  ngOnDestroy(): void { this.clearPreview(); }

  private setPreview(blob: Blob, contentType: string): void {
    this.clearPreview();
    this.receiptZoom = 1;
    this.receiptObjectUrl = URL.createObjectURL(blob);
    if (contentType.startsWith('image/')) {
      this.receiptImageUrl = this.receiptObjectUrl;
    } else {
      this.receiptPdfUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.receiptObjectUrl);
    }
  }

  private clearPreview(): void {
    if (this.receiptObjectUrl) { URL.revokeObjectURL(this.receiptObjectUrl); this.receiptObjectUrl = null; }
    this.receiptImageUrl = null;
    this.receiptPdfUrl = null;
  }

  startReject(): void { this.rejecting = true; this.rejectReason = null; this.rejectOther = ''; }
  cancelReject(): void { this.rejecting = false; }

  get isOtherReason(): boolean { return this.rejectReason === 'Other'; }

  /** The reason text actually sent: the template value, or the free text when "Other" is chosen. */
  get composedReviewNotes(): string {
    return this.isOtherReason ? this.rejectOther.trim() : (this.rejectReason ?? '');
  }

  get canConfirmReject(): boolean { return this.composedReviewNotes.length > 0; }

  confirmApprove(): void { this.approve.emit(); }

  confirmReject(): void {
    if (!this.canConfirmReject) return;
    this.reject.emit(this.composedReviewNotes);
  }
}
