import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GridModule } from '@progress/kendo-angular-grid';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { ExpenseApiService } from '../../services/expense-api.service';
import { ExpenseFormDialogComponent, ExpenseFormResult } from '../../components/expense-form-dialog/expense-form-dialog.component';
import { ExpenseDto, ExpenseListItemDto } from '../../models/expense.model';
import { switchMap, of } from 'rxjs';
import { PageHeaderActionsDirective } from '../../../../shared/directives/page-header-actions.directive';

@Component({
  selector: 'app-my-reimbursements-page',
  standalone: true,
  imports: [CommonModule, GridModule, ButtonsModule, ExpenseFormDialogComponent, PageHeaderActionsDirective],
  templateUrl: './my-reimbursements-page.component.html',
  styleUrls: ['./my-reimbursements-page.component.scss'],
})
export class MyReimbursementsPageComponent implements OnInit {
  rows: ExpenseListItemDto[] = [];
  loading = false;
  dialogOpen = false;
  editRow: ExpenseDto | null = null;

  constructor(private api: ExpenseApiService) {}

  ngOnInit(): void { this.load(); }

  load(): void {
    this.loading = true;
    this.api.getMine().subscribe({
      next: r => { this.rows = r.items; this.loading = false; },
      error: () => { this.loading = false; },
    });
  }

  openNew(): void { this.editRow = null; this.dialogOpen = true; }
  openEdit(row: ExpenseListItemDto): void {
    // Fetch the full expense (with its lines) before opening the dialog for editing.
    this.api.getById(row.id).subscribe(dto => { this.editRow = dto; this.dialogOpen = true; });
  }
  closeDialog(): void { this.dialogOpen = false; this.editRow = null; }

  onSave(result: ExpenseFormResult): void {
    if (this.editRow) {
      const id = this.editRow.id;
      this.api.update(id, result.request).pipe(
        switchMap(() => result.receipt ? this.api.uploadReceipt(id, result.receipt) : of(void 0)),
      ).subscribe(() => { this.closeDialog(); this.load(); });
    } else {
      this.api.create(result.request).pipe(
        switchMap(created => result.receipt
          ? this.api.uploadReceipt(created.id, result.receipt).pipe(switchMap(() => of(created)))
          : of(created)),
      ).subscribe(() => { this.closeDialog(); this.load(); });
    }
  }

  submit(row: ExpenseListItemDto): void { this.api.submit(row.id).subscribe(() => this.load()); }
  /** Re-submit a rejected reimbursement after fixing the flagged issue (clears the prior review server-side). */
  resubmit(row: ExpenseListItemDto): void { this.api.submit(row.id).subscribe(() => this.load()); }
  remove(row: ExpenseListItemDto): void {
    if (!confirm('Delete this reimbursement?')) return;
    this.api.delete(row.id).subscribe(() => this.load());
  }

  openReceipt(id: number): void {
    this.api.downloadReceipt(id).subscribe(blob => {
      const url = URL.createObjectURL(blob);
      window.open(url, '_blank');
      setTimeout(() => URL.revokeObjectURL(url), 60_000);
    });
  }

  /** Editing (and reuploading the photo) is allowed while Draft, awaiting review, or after a rejection. */
  canEdit(row: ExpenseListItemDto): boolean {
    return row.status === 'Draft' || row.status === 'PendingApproval' || row.status === 'Rejected';
  }
  /** Submit and Delete only apply before the reimbursement has been submitted. */
  isDraft(row: ExpenseListItemDto): boolean { return row.status === 'Draft'; }
  /** A rejected reimbursement can be fixed and re-submitted by its owner. */
  isRejected(row: ExpenseListItemDto): boolean { return row.status === 'Rejected'; }
  statusClass(status: string): string {
    return ({ Draft: 'badge-draft', PendingApproval: 'badge-pending', Approved: 'badge-approved', Paid: 'badge-paid', Rejected: 'badge-rejected' } as Record<string, string>)[status] ?? '';
  }
}
