import { Component, inject, OnInit, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { map, take } from 'rxjs/operators';
import { ButtonModule } from 'primeng/button';
import { DialogModule } from 'primeng/dialog';
import { InputTextModule } from 'primeng/inputtext';
import { InputNumberModule } from 'primeng/inputnumber';
import { SelectModule } from 'primeng/select';
import { DatePickerModule } from 'primeng/datepicker';
import { TagModule } from 'primeng/tag';
import { ToastModule } from 'primeng/toast';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { TooltipModule } from 'primeng/tooltip';
import { MessageService, ConfirmationService } from 'primeng/api';
import { PageHeaderComponent, DataTableComponent, FormDialogComponent, TableColumn } from '../../shared';
import {
  ChecksReceivedActions,
  selectChecksReceivedSaving, selectChecksReceivedError,
  BankAccountsActions, selectAllBankAccounts,
  PartnersActions, selectAllPartners,
  selectUser,
} from '../../core/store';
import { CheckReceived } from '../../core/models/check-received.model';
import { CheckReceivedService } from '../../core/services/check-received.service';
import { Partner } from '../../core/models/partner.model';

@Component({
  selector: 'app-checks-received',
  standalone: true,
  imports: [
    CommonModule, FormsModule, ReactiveFormsModule, TranslateModule,
    ButtonModule, DialogModule, InputTextModule, InputNumberModule,
    SelectModule, DatePickerModule, TagModule, ToastModule,
    ConfirmDialogModule, TooltipModule,
    PageHeaderComponent, DataTableComponent, FormDialogComponent,
  ],
  providers: [MessageService, ConfirmationService],
  templateUrl: './checks-received.component.html',
  styleUrl: './checks-received.component.scss',
})
export class ChecksReceivedComponent implements OnInit {
  private fb = inject(FormBuilder);
  private store = inject(Store);
  private messageService = inject(MessageService);
  private confirmationService = inject(ConfirmationService);
  private translate = inject(TranslateService);
  private service = inject(CheckReceivedService);

  readonly columns: TableColumn[] = [
    { field: 'check_number', header: 'CHECKS_RECEIVED.CHECK_NUMBER' },
    { field: 'drawer_name', header: 'CHECKS_RECEIVED.DRAWER' },
    { field: 'amount', header: 'CHECKS_RECEIVED.AMOUNT' },
    { field: 'receive_date', header: 'CHECKS_RECEIVED.RECEIVE_DATE' },
    { field: 'due_date', header: 'CHECKS_RECEIVED.DUE_DATE' },
    { field: 'status', header: 'COMMON.STATUS' },
    { field: 'actions', header: 'COMMON.ACTIONS' },
  ];

  saving$ = this.store.select(selectChecksReceivedSaving);
  error$ = this.store.select(selectChecksReceivedError);
  private userBranchIds: number[] = [];
  bankAccounts$ = this.store.select(selectAllBankAccounts).pipe(
    map(accounts => accounts.filter(ba => {
      if (!this.userBranchIds.length) return true;
      if (!ba.branches?.length) return true;
      return ba.branches.some(b => this.userBranchIds.includes(b.id));
    }))
  );
  clients$ = this.store.select(selectAllPartners).pipe(
    map(partners => partners.filter(p => p.is_customer))
  );
  partners = signal<Partner[]>([]);

  // Server-side pagination
  tableData = signal<CheckReceived[]>([]);
  totalRecords = signal(0);
  tableLoading = signal(false);
  first = 0;
  rows = 25;

  dialogVisible = signal(false);
  depositDialogVisible = signal(false);
  editing = signal<CheckReceived | null>(null);
  depositCheck = signal<CheckReceived | null>(null);
  form!: FormGroup;
  depositBankAccountId: number | null = null;

  ngOnInit(): void {
    this.form = this.fb.group({
      check_number: ['', Validators.required],
      amount: [0, [Validators.required, Validators.min(0.01)]],
      receive_date: [new Date(), Validators.required],
      due_date: [new Date(), Validators.required],
      partner_id: [null],
      drawer_name: ['', Validators.required],
      drawer_name_en: [''],
      drawer_name_ar: [''],
      drawer_bank: [''],
      bank_account_id: [null],
      notes: [''],
    });
    this.loadPage();
    this.store.select(selectUser).subscribe(user => {
      this.userBranchIds = user?.branches?.map(b => b.id) || [];
    });
    this.store.dispatch(BankAccountsActions.loadBankAccounts({}));
    this.store.dispatch(PartnersActions.loadPartners({}));
    this.store.select(selectAllPartners).subscribe(p => this.partners.set(p));
  }

  openNew(): void {
    this.editing.set(null);
    this.form.reset({ amount: 0, receive_date: new Date(), due_date: new Date() });
    this.dialogVisible.set(true);
  }

  edit(item: CheckReceived): void {
    this.editing.set(item);
    this.form.patchValue({
      ...item,
      receive_date: new Date(item.receive_date),
      due_date: new Date(item.due_date),
    });
    this.dialogVisible.set(true);
  }

  delete(item: CheckReceived): void {
    this.confirmationService.confirm({
      message: this.translate.instant('CHECKS_RECEIVED.CONFIRM_DELETE'),
      header: this.translate.instant('COMMON.CONFIRM'),
      icon: 'pi pi-exclamation-triangle',
      acceptButtonStyleClass: 'p-button-danger',
      accept: () => {
        this.store.dispatch(ChecksReceivedActions.deleteCheckReceived({ id: item.id }));
        this.watchResult('CHECKS_RECEIVED.DELETE_SUCCESS');
      },
    });
  }

  openDeposit(item: CheckReceived): void {
    this.depositCheck.set(item);
    this.depositBankAccountId = null;
    this.depositDialogVisible.set(true);
  }

  confirmDeposit(): void {
    if (this.depositBankAccountId && this.depositCheck()) {
      this.store.dispatch(ChecksReceivedActions.depositCheckReceived({
        id: this.depositCheck()!.id, bankAccountId: this.depositBankAccountId,
      }));
      this.depositDialogVisible.set(false);
      this.watchResult('CHECKS_RECEIVED.DEPOSIT_SUCCESS');
    }
  }

  collect(item: CheckReceived): void {
    this.confirmationService.confirm({
      message: this.translate.instant('CHECKS_RECEIVED.CONFIRM_COLLECT'),
      header: this.translate.instant('COMMON.CONFIRM'),
      icon: 'pi pi-check-circle',
      accept: () => {
        this.store.dispatch(ChecksReceivedActions.collectCheckReceived({ id: item.id }));
        this.watchResult('CHECKS_RECEIVED.COLLECT_SUCCESS');
      },
    });
  }

  returnCheck(check: CheckReceived): void {
    this.confirmationService.confirm({
      message: this.translate.instant('CHECKS_RECEIVED.CONFIRM_RETURN'),
      header: this.translate.instant('COMMON.CONFIRM'),
      accept: () => {
        this.service.returnCheck(check.id).subscribe({
          next: () => {
            this.reloadCurrentPage();
            this.messageService.add({ severity: 'success', summary: this.translate.instant('COMMON.SUCCESS'), detail: this.translate.instant('CHECKS_RECEIVED.RETURN_SUCCESS') });
          },
          error: (err) => this.messageService.add({ severity: 'error', summary: this.translate.instant('COMMON.ERROR'), detail: err.error?.message || 'Failed' }),
        });
      },
    });
  }

  loadPage(page = 1, perPage = this.rows): void {
    this.tableLoading.set(true);
    this.service.list(page, perPage).subscribe({
      next: (res) => {
        this.tableData.set(res.data);
        this.totalRecords.set(res.meta.total);
        this.tableLoading.set(false);
      },
      error: () => this.tableLoading.set(false),
    });
  }

  onPageChange(event: any): void {
    this.first = event.first;
    this.rows = event.rows;
    const page = Math.floor(event.first / event.rows) + 1;
    this.loadPage(page, event.rows);
  }

  private reloadCurrentPage(): void {
    const currentPage = Math.floor(this.first / this.rows) + 1;
    this.loadPage(currentPage);
  }

  onSave(): void {
    if (this.form.valid) {
      const val = this.form.value;
      const data = {
        ...val,
        receive_date: this.formatDate(val.receive_date),
        due_date: this.formatDate(val.due_date),
      };
      if (this.editing()) {
        this.store.dispatch(ChecksReceivedActions.updateCheckReceived({ id: this.editing()!.id, check: data }));
      } else {
        this.store.dispatch(ChecksReceivedActions.createCheckReceived({ check: data }));
      }
      const sub = this.store.select(selectChecksReceivedSaving).subscribe(saving => {
        if (!saving) {
          sub.unsubscribe();
          this.store.select(selectChecksReceivedError).pipe(take(1)).subscribe(error => {
            if (error) {
              this.messageService.add({ severity: 'error', summary: this.translate.instant('COMMON.ERROR'), detail: error });
            } else {
              this.dialogVisible.set(false);
              this.messageService.add({ severity: 'success', summary: this.translate.instant('COMMON.SUCCESS'),
                detail: this.translate.instant(this.editing() ? 'CHECKS_RECEIVED.UPDATE_SUCCESS' : 'CHECKS_RECEIVED.CREATE_SUCCESS') });
              this.reloadCurrentPage();
            }
          });
        }
      });
    } else {
      this.form.markAllAsTouched();
    }
  }

  getStatusSeverity(status: string): 'success' | 'info' | 'warn' | 'danger' | 'secondary' | 'contrast' {
    switch (status) {
      case 'collected': return 'success';
      case 'under_collection': return 'warn';
      case 'deposited': return 'info';
      case 'returned': return 'danger';
      default: return 'info';
    }
  }

  onPartnerSelect(partner: Partner | null): void {
    if (partner) {
      this.form.patchValue({
        partner_id: partner.id,
        drawer_name: partner.name_ar || partner.name,
        drawer_name_en: partner.name_en || '',
        drawer_name_ar: partner.name_ar || '',
      });
    } else {
      this.form.patchValue({ partner_id: null });
    }
  }

  getPartnerName(partnerId: number | null): string {
    if (!partnerId) return '';
    const p = this.partners().find(x => x.id === partnerId);
    return p ? (p.name_ar || p.name) : '';
  }

  retry(): void { this.loadPage(); }

  private watchResult(successKey: string): void {
    const sub = this.store.select(selectChecksReceivedSaving).subscribe(saving => {
      if (!saving) {
        sub.unsubscribe();
        this.store.select(selectChecksReceivedError).pipe(take(1)).subscribe(error => {
          if (error) {
            this.messageService.add({ severity: 'error', summary: this.translate.instant('COMMON.ERROR'), detail: error });
          } else {
            this.messageService.add({ severity: 'success', summary: this.translate.instant('COMMON.SUCCESS'), detail: this.translate.instant(successKey) });
            this.reloadCurrentPage();
          }
        });
      }
    });
  }

  private formatDate(date: Date): string {
    const y = date.getFullYear();
    const m = String(date.getMonth() + 1).padStart(2, '0');
    const d = String(date.getDate()).padStart(2, '0');
    return `${y}-${m}-${d}`;
  }
}
