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: 'doc-select',
  standalone: true,
  imports: [CommonNzModule],
  templateUrl: './doc-select.component.html',
  styleUrl: './doc-select.component.less',
})
export class DocSelectComponent {
  @Input() docLevels: Option<string>[] = [];
  @Input() docCategories: Option<string>[] = [];
  selectedCategory = '';
  selectedLevel = '';

  @Input() dataList: Knowledge.Doc[] = [];
  @Input() hiddenContent = false;
  @Input() searchable = true;
  @Input() randomCheckAble = false;
  sourceList: Knowledge.Doc[] = [];
  dataMap: Map<string, Knowledge.Doc[]> = new Map();
  checkedDto: Record<number, boolean> = {};
  searchText = '';
  filteredList: Knowledge.Doc[] = [];
  randomCount?: number;
  randomChecked = false;

  capitals: string[] = [];
  list: {
    w: string;
    items: Knowledge.Doc[];
  }[] = [];

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

  constructor() {
    this.subject$
      .pipe(
        throttleTime(50, undefined, {
          trailing: true,
        })
      )
      .subscribe(ev => {
        this.rebuildMap();
      });
  }
  ngOnInit() {
    this.rebuildMap();
  }
  clear() {
    this.searchText = '';
    this.selectedCategory = '';
    this.selectedLevel = '';
    this.checkedDto = {};
    this.dataMap.clear();
    this.rebuildMap();
  }
  @Output() onChange = new EventEmitter<Knowledge.Doc[]>();

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

  ngOnChanges(changes: SimpleChanges) {
    if (changes['dataList']) {
      if (this.dataList && this.dataList.length) {
        this.sourceList = this.dataList.slice();
      } else {
        this.sourceList = [];
      }
      this.subject$.next();
    }
  }

  onSearch() {
    this.rebuildMap();
    this.updateAllCheckedStatus();
  }
  updateCheckDto(ids: number[]) {
    ids.forEach(id => {
      const item = this.dataList.find(e => e.id === id);
      if (item) {
        this.checkedDto[id] = true;
      }
    });
  }
  onRandomCheck() {
    if (!this.randomCount) return;
    // Clear all checked items
    this.checkedDto = {};

    // Get all available options
    const availableOptions = this.sourceList.slice();

    // Ensure randomCount is within valid range
    this.randomCount = Math.max(1, Math.min(this.randomCount, availableOptions.length));

    // Randomly select options
    for (let i = 0; i < this.randomCount; i++) {
      if (availableOptions.length === 0) break;

      const randomIndex = Math.floor(Math.random() * availableOptions.length);
      const selectedOption = availableOptions.splice(randomIndex, 1)[0];
      this.checkedDto[selectedOption.id] = true;
    }

    // Update the checkbox states
    this.updateSingleChecked();
  }
  getFilterList() {
    let list = this.searchText
      ? this.sourceList.filter(w => w.name.includes(this.searchText))
      : this.sourceList.slice();
    if (this.selectedCategory) {
      list = list.filter(w => w.category === this.selectedCategory);
    }
    if (this.selectedLevel) {
      list = list.filter(w => w.level === this.selectedLevel);
    }
    return list;
  }
  rebuildMap() {
    this.filteredList = this.getFilterList();
    const capitals = this.filteredList.map(w => {
      const letters = pinyin(w.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();

    // Update all checked status based on the new filtered list
    this.updateAllCheckedStatus();
  }

  // Add this new method
  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]) => {
          const item = this.dataList.find(e => e.id === Number(id));
          if (item) {
            return item;
          }
          return null;
        })
        .filter(Boolean) as Knowledge.Doc[]
    );
  }
  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 {
    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;
    }
    this.onItemCheckedChange();
  }
}
