import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, ViewChild, effect, signal, untracked, OnInit } from '@angular/core';
import { DataTable, SortState, TableColumn } from '@shared/components/data-table/data-table';
import { Paginator } from '@shared/components/paginator/paginator';
import { SearchBar } from '@shared/components/search-bar/search-bar';
import { Modal } from '@shared/components/modal/modal';
import { ZardButtonComponent } from '@shared/components/button/button.component';
import { SortDir } from '@shared/paging/paging';
import { AgentLimit } from 'src/app/core/interfaces/agent-limit';
import { AgentLimitService } from 'src/app/core/services/agent-limit';
import { LimitForm } from '@shared/forms/limit-form/limit-form';
import { Subject, of } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';

@Component({
  standalone: true,
  selector: 'app-limits',
  templateUrl: './limits.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule, DataTable, Paginator, SearchBar, Modal, ZardButtonComponent, LimitForm],
})
export class LimitsPage implements OnInit {
  rows = signal<AgentLimit[]>([]);
  total = signal(0);
  loading = signal(false);
  page = signal(1);
  size = signal(10);
  search = signal('');
  sort = signal<SortState>({ key: 'code', dir: 'asc' });
  selectedActif = signal<boolean | null>(null);

  modalOpen = signal(false);
  modalTitle = signal('Nouvelle limite');
  editingItem = signal<AgentLimit | null>(null);

  // Live search
  private searchSubject = new Subject<string>();

  @ViewChild(LimitForm) formComp?: LimitForm;

  cols: TableColumn<AgentLimit>[] = [
    { key: 'code', label: 'Code', sortable: true },
    { key: 'configCode', label: 'Config', sortable: true },
    { key: 'nom', label: 'Nom', sortable: true },
    {
      key: 'isDefault',
      label: 'Défaut',
      cell: (l) =>
        l.isDefault
          ? '<span class="inline-flex items-center gap-1 px-2 py-1 rounded bg-primary/10 text-primary text-xs font-medium"><i class="icon-star"></i> Par défaut</span>'
          : '<span class="text-muted-foreground">—</span>',
    },
    {
      key: 'actif',
      label: 'Actif',
      cell: (l) =>
        l.actif
          ? '<span class="inline-flex items-center gap-1 px-2 py-1 rounded bg-green-500/10 text-green-600 dark:text-green-400 text-xs font-medium"><i class="icon-check"></i> Actif</span>'
          : '<span class="inline-flex items-center gap-1 px-2 py-1 rounded bg-gray-500/10 text-gray-600 dark:text-gray-400 text-xs font-medium"><i class="icon-x"></i> Inactif</span>',
    },
    {
      key: 'betMin',
      label: 'Min Bet',
      cell: (l) => (l.betMin ?? 0).toLocaleString('fr-FR'),
    },
    {
      key: 'betMax',
      label: 'Max Bet',
      cell: (l) => (l.betMax ?? 0).toLocaleString('fr-FR'),
    },
    {
      key: 'maxBet',
      label: 'Max Bet (tx)',
      cell: (l) => (l.maxBet ?? 0).toLocaleString('fr-FR'),
    },
    {
      key: 'maxDisburseBet',
      label: 'Max Disburse',
      cell: (l) => (l.maxDisburseBet ?? 0).toLocaleString('fr-FR'),
    },
    {
      key: 'airtimeMin',
      label: 'Airtime Min',
      cell: (l) => (l.airtimeMin ?? 0).toLocaleString('fr-FR'),
    },
    {
      key: 'airtimeMax',
      label: 'Airtime Max',
      cell: (l) => (l.airtimeMax ?? 0).toLocaleString('fr-FR'),
    },
  ];

  constructor(private api: AgentLimitService) {
    effect(() => {
      // Only trigger fetch when page, size, or sort changes (not search - handled by searchSubject)
      const searchValue = this.search();
      const params = {
        page: this.page(),
        size: this.size(),
        search: searchValue,
        sortKey: this.sort().key,
        sortDir: this.sort().dir as SortDir,
      };
      // Only fetch if search is empty (search is handled by searchSubject)
      if (!searchValue.trim()) {
        untracked(() => this.fetch(params));
      }
    });

    // Setup live search with debounce
    this.searchSubject
      .pipe(
        debounceTime(300),
        distinctUntilChanged(),
        switchMap((query) => {
          if (query.trim()) {
            // Use search API which returns array
            return this.api.search(query);
          } else {
            // If empty, use normal list
            return this.api.list({
              page: this.page(),
              size: this.size(),
              search: '',
              sortKey: this.sort().key,
              sortDir: this.sort().dir as SortDir,
            }).pipe(
              switchMap((res) => {
                // Convert PagedResult to array for consistency
                return of(res.content);
              })
            );
          }
        })
      )
      .subscribe({
        next: (res) => {
          // Search API always returns array
          if (Array.isArray(res)) {
            this.rows.set(res);
            this.total.set(res.length);
          }
          this.loading.set(false);
        },
        error: (err) => {
          console.error('Search error:', err);
          this.rows.set([]);
          this.total.set(0);
          this.loading.set(false);
        },
      });
  }

  ngOnInit() {
    // Initial fetch
    this.fetch({
      page: this.page(),
      size: this.size(),
      search: this.search(),
      sortKey: this.sort().key,
      sortDir: this.sort().dir as SortDir,
    });
  }

  private fetch(params: { page: number; size: number; search: string; sortKey: string; sortDir: SortDir }) {
    // Don't fetch if there's a search query - it's handled by searchSubject
    const searchQuery = params.search.trim();
    if (searchQuery) {
      return; // Search is handled by searchSubject subscription
    }

    this.loading.set(true);
    const actif = this.selectedActif();

    if (actif !== null) {
      // Filter by actif status - returns array
      this.api.getByActif(actif).subscribe({
        next: (res: AgentLimit[]) => {
          this.rows.set(res);
          this.total.set(res.length);
          this.loading.set(false);
        },
        error: () => {
          this.rows.set([]);
          this.total.set(0);
          this.loading.set(false);
        },
      });
    } else {
      // Normal list with pagination
      this.api.list(params).subscribe({
        next: (res) => {
          this.rows.set(res.content);
          this.total.set(res.pageable.total);
          this.loading.set(false);
        },
        error: () => {
          this.rows.set([]);
          this.total.set(0);
          this.loading.set(false);
        },
      });
    }
  }

  onSearch(q: string) {
    this.search.set(q);
    this.page.set(1);
    // Trigger search via subject for live search
    if (q.trim()) {
      this.loading.set(true);
      this.searchSubject.next(q);
    } else {
      // If empty, fetch normally
      this.fetch({
        page: this.page(),
        size: this.size(),
        search: '',
        sortKey: this.sort().key,
        sortDir: this.sort().dir as SortDir,
      });
    }
  }

  onActifFilter(actif: boolean | null) {
    this.selectedActif.set(actif);
    this.page.set(1);
    this.fetch({
      page: this.page(),
      size: this.size(),
      search: this.search(),
      sortKey: this.sort().key,
      sortDir: this.sort().dir as SortDir,
    });
  }
  openCreate() { this.modalTitle.set('Nouvelle limite'); this.editingItem.set(null); queueMicrotask(() => this.modalOpen.set(true)); }
  openEdit(row: AgentLimit) { this.modalTitle.set('Modifier la limite'); this.editingItem.set(row); queueMicrotask(() => this.modalOpen.set(true)); }
  closeModal() { this.modalOpen.set(false); }
  submitChildForm() { this.formComp?.onSubmit(); }

  onFormSave(payload: Partial<AgentLimit>) {
    const current = this.editingItem();
    const isSettingDefault = payload.isDefault === true;
    const wasDefault = current?.isDefault;
    
    // If setting as default and it wasn't default before, show confirmation
    if (isSettingDefault && !wasDefault) {
      if (!confirm('Définir cette limite comme limite par défaut ?\n\nTous les agents recevront automatiquement cette limite, et l\'ancienne limite par défaut perdra son statut.')) {
        return;
      }
    }
    
    const req$ = current?.id ? this.api.update(current.id, payload) : this.api.create(payload as Omit<AgentLimit, 'id'>);
    req$.subscribe({
      next: (result) => {
        if (!result && current?.id) {
          // Update failed
          alert('Erreur lors de la sauvegarde de la limite');
          return;
        }
        this.closeModal();
        this.fetch({
          page: this.page(),
          size: this.size(),
          search: this.search(),
          sortKey: this.sort().key,
          sortDir: this.sort().dir as SortDir,
        });
        if (isSettingDefault && !wasDefault) {
          alert('La limite a été définie comme limite par défaut. Tous les agents ont été mis à jour.');
        }
      },
      error: (err) => {
        console.error('Error saving limit:', err);
        alert('Erreur lors de la sauvegarde de la limite');
      },
    });
  }

  remove(row: AgentLimit) {
    if (!confirm(`Supprimer la limite ${row.code} ?`)) return;
    this.api.delete(row.id).subscribe(() => {
      this.fetch({
        page: this.page(),
        size: this.size(),
        search: this.search(),
        sortKey: this.sort().key,
        sortDir: this.sort().dir as SortDir,
      });
    });
  }
}


