import { Component, ElementRef, EventEmitter, Input, Output, SimpleChanges, ViewChild } from '@angular/core';
import { pinyin } from 'pinyin-pro';
import { Subject, throttleTime } from 'rxjs';
import { CommonNzModule } from '../../common.nz.module';

@Component({
  selector: 'user-search',
  standalone: true,
  imports: [CommonNzModule],
  templateUrl: './user-search.component.html',
  styleUrl: './user-search.component.less',
})
export class UserSearchComponent {
  @Input() hiddenContent = false;
  @Input() userList: Auth.User[] = [];
  loading = false;
  sources: Auth.User[] = [];
  dataMap: Map<string, Auth.User[]> = new Map();
  checkedDto: Record<string, boolean> = {};

  search = {
    text: '',
  };
  filteredList: Auth.User[] = [];
  capitals: string[] = [];
  list: {
    w: string;
    items: Auth.User[];
  }[] = [];

  private subject$ = new Subject<void>();

  constructor() {
    this.subject$
      .pipe(
        throttleTime(50, undefined, {
          trailing: true,
        })
      )
      .subscribe(ev => {
        this.rebuildMap();
      });
  }
  ngOnInit() {
    this.rebuildMap();
  }
  clear() {
    this.search.text = '';
    this.checkedDto = {};
    this.dataMap.clear();
    this.rebuildMap();
  }
  merge(users: Option<string>[]) {
    users.forEach(u => {
      this.checkedDto[u.value] = true;
    });
  }

  @Output() onChange = new EventEmitter<string[]>();

  @ViewChild('content') content!: ElementRef<HTMLDivElement>;

  ngOnChanges(changes: SimpleChanges) {
    if (changes['userList']) {
      if (this.userList && this.userList.length) {
        this.sources = this.userList.map(user => ({
          ...user,
          label: `${user.name}(${user.job}), ${user.job}`,
        }));
      } else {
        this.sources = [];
      }
      this.subject$.next();
    }
  }
  onSearch() {
    this.rebuildMap();
    this.updateAllCheckedStatus();
  }
  rebuildMap() {
    this.filteredList = this.search.text
      ? this.sources.filter(w => w.name.includes(this.search.text))
      : this.sources.slice();

    const capitals = this.filteredList.map(w => {
      const name = w.name.split('(')[0]; // Extract the name from the label
      const letters = pinyin(name, { toneType: 'none' });
      const firstLetter = letters[0];
      const isAlphabet = /[a-z]/i.test(firstLetter);
      return {
        w: isAlphabet ? firstLetter.toUpperCase() : '*',
        d: w,
      };
    });

    this.dataMap.clear();
    capitals.forEach(c => {
      if (!this.dataMap.get(c.w)) {
        this.dataMap.set(c.w, []);
      }
      this.dataMap.get(c.w)?.push(c.d);
    });
    this.capitals = this.getCapitals();
    this.list = this.getList();
    this.updateAllCheckedStatus();
  }

  updateAllCheckedStatus(): void {
    if (this.filteredList.length === 0) {
      this.allChecked = false;
      this.indeterminate = false;
    } else if (this.filteredList.every(item => this.checkedDto[item.id])) {
      this.allChecked = true;
      this.indeterminate = false;
    } else if (this.filteredList.some(item => this.checkedDto[item.id])) {
      this.allChecked = false;
      this.indeterminate = true;
    } else {
      this.allChecked = false;
      this.indeterminate = false;
    }
  }

  onItemCheckedChange() {
    this.onChange.emit(
      Object.entries(this.checkedDto)
        .filter(([_, v]) => Boolean(v))
        .map(([id]) => String(id))
    );
  }
  onLocate(w: string) {
    const dom = this.content.nativeElement;
    if (!dom) return;
    const target = dom.querySelector(`[data="${w}"]`);
    if (target) {
      target.scrollIntoView({
        block: 'start',
        behavior: 'smooth',
      });
    }
  }

  getCapitals() {
    return Array.from(this.dataMap)
      .map(c => c[0])
      .sort();
  }
  getList() {
    return this.capitals.map(c => {
      return {
        w: c,
        items: this.dataMap.get(c) || [],
      };
    });
  }

  allChecked = false;
  indeterminate = false;

  get isAllCheckboxDisabled(): boolean {
    return this.filteredList.length === 0;
  }

  updateAllChecked(): void {
    if (this.isAllCheckboxDisabled) return;

    this.indeterminate = false;
    if (this.allChecked) {
      this.filteredList.forEach(item => (this.checkedDto[item.id] = true));
    } else {
      this.filteredList.forEach(item => (this.checkedDto[item.id] = false));
    }
    this.onItemCheckedChange();
  }

  updateSingleChecked(): void {
    this.updateAllCheckedStatus();
    this.onItemCheckedChange();
  }

  additionalLabel(user: Auth.User) {
    const { job } = user;
    return job ? `(${job})` : '';
  }
}
