import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { GridModule, GridDataResult, PageChangeEvent } from '@progress/kendo-angular-grid';
import { InputsModule } from '@progress/kendo-angular-inputs';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { DialogsModule } from '@progress/kendo-angular-dialog';
import { DateInputsModule } from '@progress/kendo-angular-dateinputs';
import { GivingApiService } from '../../services/giving-api.service';
import { GivingCategoryApiService } from '../../services/giving-category-api.service';
import { MemberApiService } from '../../../members/services/member-api.service';
import { MemberListItemDto, memberDisplayName } from '../../../members/models/member.model';
import {
  GivingListItemDto, GivingCategoryDto, CreateGivingRequest, PaymentMethod, PagedResult,
} from '../../models/giving.model';
import { PAYMENT_METHOD_OPTIONS } from '../../../../shared/i18n/option-lists';
import { PageHeaderActionsDirective } from '../../../../shared/directives/page-header-actions.directive';

/** Flattened member item with a single displayName field for the dropdown. */
interface MemberOption {
  id: number;
  displayName: string;
}

@Component({
  selector: 'app-givings-page',
  standalone: true,
  imports: [
    CommonModule, FormsModule, GridModule, InputsModule, ButtonsModule,
    DropDownsModule, DialogsModule, DateInputsModule, PageHeaderActionsDirective,
  ],
  templateUrl: './givings-page.component.html',
  styleUrls: ['./givings-page.component.scss'],
})
export class GivingsPageComponent implements OnInit {
  gridData: GridDataResult = { data: [], total: 0 };
  page = 1;
  pageSize = 20;
  isLoading = false;

  search = '';
  filterCategoryId: number | null = null;
  categories: GivingCategoryDto[] = [];

  readonly paymentMethods = PAYMENT_METHOD_OPTIONS;

  memberResults: MemberOption[] = [];

  showDialog = false;
  editingId: number | null = null;
  form: CreateGivingRequest = this.blankForm();
  selectedMemberId: number | null = null;

  /** Separate Date field for kendo-datepicker (which binds Date, not string). */
  givingDateValue: Date = new Date();

  constructor(
    private api: GivingApiService,
    private categoryApi: GivingCategoryApiService,
    private memberApi: MemberApiService,
  ) {}

  ngOnInit(): void {
    this.categoryApi.getAll(false).subscribe(c => this.categories = c);
    this.load();
  }

  load(): void {
    this.isLoading = true;
    this.api.getPaged({
      page: this.page, pageSize: this.pageSize,
      search: this.search || undefined,
      categoryId: this.filterCategoryId ?? undefined,
    }).subscribe({
      next: (r: PagedResult<GivingListItemDto>) => {
        this.gridData = { data: r.items, total: r.totalCount }; this.isLoading = false;
      },
      error: () => { this.isLoading = false; },
    });
  }

  onPageChange(e: PageChangeEvent): void {
    this.page = e.skip / this.pageSize + 1; this.pageSize = e.take; this.load();
  }

  onSearch(): void { this.page = 1; this.load(); }

  onMemberFilter(term: string): void {
    if (!term || term.length < 1) { this.memberResults = []; return; }
    this.memberApi.getPaged({ search: term, pageSize: 10 })
      .subscribe(r => {
        this.memberResults = r.items.map((m: MemberListItemDto) => ({
          id: m.id,
          displayName: memberDisplayName(m),
        }));
      });
  }

  openAdd(): void {
    this.editingId = null;
    this.form = this.blankForm();
    this.selectedMemberId = null;
    this.givingDateValue = new Date();
    this.memberResults = [];
    this.showDialog = true;
  }

  /** Called from template valueChange — receives the primitive id (number | null). */
  onMemberIdSelected(id: number | null): void {
    this.selectedMemberId = id ?? null;
    this.form.memberId = this.selectedMemberId;
  }

  toggleAnonymous(): void {
    this.form.isAnonymous = !this.form.isAnonymous;
    if (this.form.isAnonymous) {
      this.form.memberId = null;
      this.selectedMemberId = null;
    }
  }

  save(): void {
    // Sync the datepicker Date back to the ISO string field.
    this.form.givingDate = this.toIso(this.givingDateValue ?? new Date());

    if (this.editingId) {
      this.api.update(this.editingId, this.form).subscribe(() => { this.showDialog = false; this.load(); });
    } else {
      this.api.create(this.form).subscribe(() => { this.showDialog = false; this.load(); });
    }
  }

  delete(g: GivingListItemDto): void {
    if (!confirm('Delete this giving record?')) return;
    this.api.delete(g.id).subscribe({
      next: () => this.load(),
      error: (err: { error?: { message?: string } }) =>
        alert(err?.error?.message ?? 'Delete failed (record may belong to a locked session).'),
    });
  }

  private blankForm(): CreateGivingRequest {
    return {
      memberId: null,
      givingCategoryId: this.categories[0]?.id ?? 0,
      amount: 0,
      paymentMethod: 'Cash',
      checkNumber: null,
      zelleReferenceCode: null,
      payPalTransactionId: null,
      givingDate: this.toIso(new Date()),
      isAnonymous: false,
      notes: null,
    };
  }

  // Format using LOCAL date components — NOT toISOString(), which converts to UTC and
  // rolls the date forward a day for behind-UTC users when the Date carries an evening time.
  private toIso(d: Date): string {
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    return `${y}-${m}-${day}`;
  }
}
