import { Component, inject, OnInit, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { take, map } from 'rxjs/operators';
import { TableModule } from 'primeng/table';
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 { ToggleSwitchModule } from 'primeng/toggleswitch';
import { TagModule } from 'primeng/tag';
import { ToastModule } from 'primeng/toast';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { MessageService, ConfirmationService } from 'primeng/api';
import { HttpClient } from '@angular/common/http';
import { PageHeaderComponent, DataTableComponent, FormDialogComponent, TableColumn } from '../../shared';
import {
  PettyCashActions, selectAllPettyCash, selectPettyCashLoading,
  selectPettyCashSaving, selectPettyCashError,
  selectPettyCashTransactions,
  AccountsActions, selectAllAccounts,
  BranchesActions, selectAllBranches,
  selectUser,
} from '../../core/store';
import { PettyCash } from '../../core/models/petty-cash.model';
import { Account } from '../../core/models/account.model';
import { JournalEntryService } from '../../core/services/journal-entry.service';
import { LanguageService } from '../../core/services/language.service';
import { environment } from '../../../environments/environment';

@Component({
  selector: 'app-petty-cash',
  standalone: true,
  imports: [
    CommonModule, ReactiveFormsModule, TranslateModule,
    TableModule, ButtonModule, DialogModule, InputTextModule, InputNumberModule,
    SelectModule, DatePickerModule, ToggleSwitchModule, TagModule, ToastModule,
    ConfirmDialogModule,
    PageHeaderComponent, DataTableComponent, FormDialogComponent,
  ],
  providers: [MessageService, ConfirmationService],
  templateUrl: './petty-cash.component.html',
  styleUrl: './petty-cash.component.scss',
})
export class PettyCashComponent implements OnInit {
  readonly columns: TableColumn[] = [
    { field: 'name', header: 'PETTY_CASH.NAME' },
    { field: 'account', header: 'PETTY_CASH.ACCOUNT' },
    { field: 'branch', header: 'PETTY_CASH.BRANCH' },
    { field: 'max_amount', header: 'PETTY_CASH.MAX_AMOUNT' },
    { field: 'current_balance', header: 'PETTY_CASH.CURRENT_BALANCE' },
    { field: 'status', header: 'COMMON.STATUS' },
    { field: 'actions', header: 'COMMON.ACTIONS' },
  ];

  private fb = inject(FormBuilder);
  private store = inject(Store);
  private messageService = inject(MessageService);
  private confirmationService = inject(ConfirmationService);
  private translate = inject(TranslateService);
  private journalEntryService = inject(JournalEntryService);
  private http = inject(HttpClient);
  lang = inject(LanguageService);

  loading$ = this.store.select(selectPettyCashLoading);
  saving$ = this.store.select(selectPettyCashSaving);
  error$ = this.store.select(selectPettyCashError);
  transactions$ = this.store.select(selectPettyCashTransactions);
  accounts$ = this.store.select(selectAllAccounts);
  private userBranchIds: number[] = [];
  branches$ = this.store.select(selectAllBranches).pipe(
    map(branches => {
      if (!this.userBranchIds.length) return branches;
      return branches.filter(b => this.userBranchIds.includes(b.id));
    })
  );

  /** Items with journal-based balance */
  items = signal<(PettyCash & { journal_balance: number })[]>([]);
  dialogVisible = signal(false);
  txDialogVisible = signal(false);
  editing = signal<PettyCash | null>(null);
  selectedItem = signal<(PettyCash & { journal_balance: number }) | null>(null);
  form!: FormGroup;
  txForm!: FormGroup;
  detailAccounts = signal<Account[]>([]);
  accountEntries = signal<{ date: string; entry_number: string; description: string; debit: number; credit: number }[]>([]);
  loadingEntries = signal(false);
  selectedBalance = signal<number>(0);

  txTypeOptions: { label: string; value: string }[] = [];
  private rawItems: PettyCash[] = [];
  private balanceMap: Record<number, number> = {};

  ngOnInit(): void {
    this.form = this.fb.group({
      name: ['', Validators.required],
      name_en: [''],
      name_ar: [''],
      account_id: [null],
      branch_id: [null],
      max_amount: [0, [Validators.required, Validators.min(0)]],
      is_active: [true],
    });
    this.txForm = this.fb.group({
      type: ['receipt', Validators.required],
      amount: [0, [Validators.required, Validators.min(0.01)]],
      date: [new Date(), Validators.required],
      description: ['', Validators.required],
      reference: [''],
    });
    this.store.select(selectUser).subscribe(user => {
      this.userBranchIds = user?.branches?.map(b => b.id) || [];
    });
    this.store.dispatch(PettyCashActions.loadPettyCashList({}));
    this.store.dispatch(AccountsActions.loadAccounts({}));
    this.store.dispatch(BranchesActions.loadBranches({}));

    this.store.select(selectAllPettyCash).subscribe(pcList => {
      this.rawItems = pcList;
      this.mergeBalances();
    });

    this.loadAccountBalances();

    this.accounts$.subscribe(accounts => {
      this.detailAccounts.set(accounts.filter(a => a.account_type === 'detail'));
    });
    this.txTypeOptions = [
      { label: this.translate.instant('PETTY_CASH.TYPE_RECEIPT'), value: 'receipt' },
      { label: this.translate.instant('PETTY_CASH.TYPE_PAYMENT'), value: 'payment' },
    ];
  }

  private mergeBalances(): void {
    this.items.set(this.rawItems.map(pc => ({
      ...pc,
      journal_balance: this.balanceMap[pc.account_id] ?? 0,
    })));
  }

  loadAccountBalances(): void {
    this.http.get<any>(`${environment.apiUrl}/accounting/reports/trial-balance`).subscribe({
      next: (res) => {
        this.balanceMap = {};
        for (const row of res.data || []) {
          this.balanceMap[row.account_id] = Number(row.balance) || 0;
        }
        this.mergeBalances();
      },
      error: () => {},
    });
  }

  openNew(): void {
    this.editing.set(null);
    this.form.reset({ max_amount: 0, is_active: true });
    this.dialogVisible.set(true);
  }

  edit(item: PettyCash): void {
    this.editing.set(item);
    this.form.patchValue(item);
    this.dialogVisible.set(true);
  }

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

  viewTransactions(item: PettyCash & { journal_balance: number }): void {
    this.selectedItem.set(item);
    this.selectedBalance.set(item.journal_balance);
    this.store.dispatch(PettyCashActions.loadTransactions({ pettyCashId: item.id }));
    this.loadAccountEntries(item.account_id);
    this.txDialogVisible.set(true);
  }

  private loadAccountEntries(accountId: number): void {
    this.loadingEntries.set(true);
    this.journalEntryService.listByAccount(accountId).subscribe({
      next: (res) => {
        const entries: { date: string; entry_number: string; description: string; debit: number; credit: number }[] = [];
        for (const je of res.data) {
          if (je.status !== 'posted') continue;
          for (const line of je.lines) {
            if (line.account_id === accountId) {
              entries.push({
                date: je.date,
                entry_number: je.entry_number || '',
                description: je.description || line.description || '',
                debit: parseFloat(String(line.debit)) || 0,
                credit: parseFloat(String(line.credit)) || 0,
              });
            }
          }
        }
        entries.sort((a, b) => b.date.localeCompare(a.date));
        this.accountEntries.set(entries);
        let bal = 0;
        for (const e of entries) { bal += e.debit - e.credit; }
        this.selectedBalance.set(bal);
        this.loadingEntries.set(false);
      },
      error: () => { this.loadingEntries.set(false); this.accountEntries.set([]); },
    });
  }

  openNewTx(): void {
    this.txForm.reset({ type: 'receipt', amount: 0, date: new Date() });
  }

  addTransaction(): void {
    if (this.txForm.valid && this.selectedItem()) {
      const val = this.txForm.value;
      this.store.dispatch(PettyCashActions.createTransaction({
        pettyCashId: this.selectedItem()!.id,
        transaction: { ...val, date: this.formatDate(val.date) },
      }));
      const sub = this.store.select(selectPettyCashSaving).subscribe(saving => {
        if (!saving) {
          sub.unsubscribe();
          this.store.select(selectPettyCashError).pipe(take(1)).subscribe(error => {
            if (error) {
              this.messageService.add({ severity: 'error', summary: this.translate.instant('COMMON.ERROR'), detail: error });
            } else {
              this.txForm.reset({ type: 'receipt', amount: 0, date: new Date() });
              this.messageService.add({ severity: 'success', summary: this.translate.instant('COMMON.SUCCESS'), detail: this.translate.instant('PETTY_CASH.TX_CREATE_SUCCESS') });
              this.store.dispatch(PettyCashActions.loadPettyCashList({ forceReload: true }));
              this.store.dispatch(PettyCashActions.loadTransactions({ pettyCashId: this.selectedItem()!.id }));
              this.loadAccountEntries(this.selectedItem()!.account_id);
              this.loadAccountBalances();
            }
          });
        }
      });
    }
  }

  deleteTx(txId: number): void {
    if (this.selectedItem()) {
      const pcId = this.selectedItem()!.id;
      this.store.dispatch(PettyCashActions.deleteTransaction({ pettyCashId: pcId, transactionId: txId }));
      const sub = this.store.select(selectPettyCashSaving).subscribe(saving => {
        if (!saving) {
          sub.unsubscribe();
          this.store.select(selectPettyCashError).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('PETTY_CASH.TX_DELETE_SUCCESS') });
              this.store.dispatch(PettyCashActions.loadPettyCashList({ forceReload: true }));
              this.store.dispatch(PettyCashActions.loadTransactions({ pettyCashId: pcId }));
              if (this.selectedItem()) this.loadAccountEntries(this.selectedItem()!.account_id);
              this.loadAccountBalances();
            }
          });
        }
      });
    }
  }

  onSave(): void {
    if (this.form.valid) {
      const data = this.form.value;
      if (this.editing()) {
        this.store.dispatch(PettyCashActions.updatePettyCash({ id: this.editing()!.id, pettyCash: data }));
      } else {
        this.store.dispatch(PettyCashActions.createPettyCash({ pettyCash: data }));
      }
      const sub = this.store.select(selectPettyCashSaving).subscribe(saving => {
        if (!saving) {
          sub.unsubscribe();
          this.store.select(selectPettyCashError).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() ? 'PETTY_CASH.UPDATE_SUCCESS' : 'PETTY_CASH.CREATE_SUCCESS') });
            }
          });
        }
      });
    } else {
      this.form.markAllAsTouched();
    }
  }

  retry(): void {
    this.store.dispatch(PettyCashActions.loadPettyCashList({ forceReload: true }));
    this.loadAccountBalances();
  }

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

  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}`;
  }
}
