import { AfterViewInit, Component, OnDestroy, OnInit } from "@angular/core";
import { HTTPQuery } from "../interfaces/http-query";
import { Subject, debounceTime, takeUntil } from "rxjs";
import { FormControl } from "@angular/forms";
import { HelpersService } from "../services/helpers.service";
import { LoadingService } from "../services/loading.service";
import { ApiService } from "../services/api.service";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { ConfirmationModalComponent } from "src/app/pages/dashboard/components/confirmation-modal/confirmation-modal.component";

@Component({
  selector: "base-crud",
  template: "",
})
export class BaseCrudComponent<T> implements OnInit, OnDestroy, AfterViewInit {
  pageTitle = "";

  queryLimit = 10;
  queryPage = 1;
  querySort = "-created_at";
  queries: HTTPQuery = {};

  searchFields = "";
  searchForm = new FormControl();
  searchSubs$ = new Subject<void>();

  dataSource: T[] = [];
  dataSourceLength = 0;
  dataSourceTotal = 0;
  dataSourceSubs$ = new Subject<void>();

  pageSizeOptions = [5, 10, 25, 50];

  constructor(
    public helpers: HelpersService,
    public loading: LoadingService,
    public api: ApiService<T>,
    public modal: NgbModal
  ) {
    this.queries = {
      limit: this.queryLimit,
      page: this.queryPage,
      sort: this.querySort,
    };
  }

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

  ngAfterViewInit(): void {
    this.searchForm.valueChanges
      .pipe(debounceTime(1000), takeUntil(this.searchSubs$))
      .subscribe((value) => {
        if (value.trim().length >= 3 && !value.startsWith(" ")) {
          this.queries = {
            ...this.queries,
            search: {
              fields: this.searchFields,
              value: value,
            },
          };
        } else if (value.trim().length === 0 && !value.startsWith(" ")) {
          delete this.queries["search"];
        } else {
          return;
        }
        this.getAll(false);
      });
  }

  ngOnDestroy(): void {
    this.dataSourceSubs$.next();
    this.dataSourceSubs$.complete();

    this.searchSubs$.next();
    this.searchSubs$.complete();

    this.loading.hide();
  }

  getAll(isTotalChange = true): void {
    this.loading.show();
    this.api
      .getAll(this.queries)
      .pipe(takeUntil(this.dataSourceSubs$))
      .subscribe({
        next: ({ data, total }) => {
          this.loading.hide();
          this.dataSource = data;
          this.dataSourceLength = total;
          if (isTotalChange) this.dataSourceTotal = total;
        },
        error: () => {
          this.loading.hide();
          this.helpers.toast("error", `Gagal mengambil data`);
        },
      });
  }

  onPageSizeChange(pageSize: Event): void {
    const value = parseInt((pageSize.target as HTMLInputElement).value);
    this.queryLimit = value;
    this.queries = {
      ...this.queries,
      limit: this.queryLimit,
      page: this.queryPage,
    };
    this.getAll(false);
  }

  onPaginateChange(page: any): void {
    this.queryPage = page;
    this.queries = {
      ...this.queries,
      page: this.queryPage,
    };
    this.getAll(false);
  }

  parseNumber(value: number): number {
    return this.queries["page"] && this.queries["limit"]
      ? value + 1 + (this.queries["page"] - 1) * this.queries["limit"]
      : value;
  }

  onDeleteData(
    id: string | number,
    subject: string | null | undefined = null
  ): void {
    const modalRef = this.modal.open(ConfirmationModalComponent, {
      size: "sm",
    });
    modalRef.componentInstance.modalType = 2;
    modalRef.componentInstance.message = `Anda yakin ingin menghapus ${
      subject ? `<span class='fw-medium text-danger'>${subject}</span>` : "data"
    } ?`;
    modalRef.result.then(
      (result) => {
        if (result) {
          this.api.delete(id).subscribe({
            next: () => {
              this.helpers.toast(
                "success",
                `Berhasil menghapus ${subject ?? "data"}`
              );
              this.getAll(true);
            },
            error: () => {
              this.helpers.toast(
                "error",
                `Gagal menghapus data ${subject} ?? 'data'`
              );
            },
          });
        }
      },
      () => {}
    );
  }
}
