import { CommonModule } from '@angular/common';
import {
  ChangeDetectionStrategy,
  Component,
  ViewChild,
  effect,
  signal,
  untracked,
} 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 { ZardCardComponent } from '@shared/components/card/card.component';
import { ZardSelectComponent } from '@shared/components/select/select.component';
import { ZardSelectItemComponent } from '@shared/components/select/select-item.component';
import { ZardFormModule } from '@shared/components/form/form.module';
import { SortDir } from '@shared/paging/paging';
import { Agent, AgentFamilyMember } from 'src/app/core/interfaces/agent';
import { AgentService } from 'src/app/core/services/agent';
import { AgentFamilyMemberService } from 'src/app/core/services/agent-family-member';
import { TpeService } from 'src/app/core/services/tpe';
import { TpeDevice, TpeStatus } from 'src/app/core/interfaces/tpe';
import { AgentFullForm } from '@shared/forms/agent-full-form/agent-full-form';
import { forkJoin, of } from 'rxjs';
import { switchMap, catchError } from 'rxjs/operators';

@Component({
  standalone: true,
  selector: 'app-agents',
  templateUrl: './agents.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    CommonModule,
    DataTable,
    Paginator,
    SearchBar,
    Modal,
    ZardButtonComponent,
    ZardCardComponent,
    ZardSelectComponent,
    ZardSelectItemComponent,
    ZardFormModule,
    AgentFullForm,
  ],
})
export class AgentsPage {
  rows = signal<Agent[]>([]);
  total = signal(0);
  loading = signal(false);

  page = signal(1);
  size = signal(10);
  search = signal('');
  sort = signal<SortState>({ key: 'code', dir: 'asc' });

  modalOpen = signal(false);
  modalTitle = signal('Nouvel agent');
  editingItem = signal<Agent | null>(null);

  detailModalOpen = signal(false);
  detailItem = signal<Agent | null>(null);
  detailFamilyMembers = signal<AgentFamilyMember[]>([]);

  // TPE Assignment modal
  assignTpeModalOpen = signal(false);
  assigningAgent = signal<Agent | null>(null);
  availableTpes = signal<TpeDevice[]>([]);
  selectedTpeId = signal<string>('');
  tpesLoading = signal(false);

  @ViewChild(AgentFullForm) formComp?: AgentFullForm;

  formatTpeStatut(statut: TpeStatus): string {
    const statutMap: Record<string, string> = {
      VALIDE: 'Valide',
      INVALIDE: 'Invalide',
      EN_PANNE: 'En panne',
      BLOQUE: 'Bloqué',
      DISPONIBLE: 'Disponible',
      AFFECTE: 'Affecté',
      EN_MAINTENANCE: 'En maintenance',
      HORS_SERVICE: 'Hors service',
      VOLE: 'Volé',
    };
    return statutMap[statut] || statut;
  }

  cols: TableColumn<Agent>[] = [
    { key: 'code', label: 'Code', sortable: true, defaultVisible: true },
    { key: 'nomPrenom', label: 'Nom complet', sortable: true, defaultVisible: true, cell: (a) => `${a.nom} ${a.prenom}` },
    { key: 'profile', label: 'Profil', sortable: true, defaultVisible: true },
    { key: 'statut', label: 'Statut', sortable: true, defaultVisible: true, cell: (a) => this.renderStatutBadge(a.statut) },
    { key: 'phone', label: 'Téléphone', sortable: true, defaultVisible: true },
    { key: 'zone', label: 'Zone', sortable: true },
    { key: 'kiosk', label: 'Kiosque', sortable: true },
    { key: 'tpes', label: 'TPE', cell: (a) => `${(this.getAgentTpes(a.id) || []).length}` },
    { key: 'limites', label: 'Limites', cell: (a) => this.formatLimits(a) },
    { key: 'dateEmbauche', label: 'Embauché le', cell: (a) => (a.dateEmbauche ? new Date(a.dateEmbauche).toLocaleDateString() : '') },
  ];

  tpeMap = new Map<string, TpeDevice>();
  agentTpesMap = new Map<string, TpeDevice[]>();

  constructor(
    private api: AgentService,
    private tpeSvc: TpeService,
    private familyMemberService: AgentFamilyMemberService
  ) {
    // Preload TPE maps for display
    this.tpeSvc
      .list({ page: 1, size: 200, search: '', sortKey: 'imei', sortDir: 'asc' } as any)
      .subscribe((res) => {
        const tpes = res.content as TpeDevice[];
        this.rebuildTpeMaps(tpes);
      });
    effect(() => {
      const params = {
        page: this.page(),
        size: this.size(),
        search: this.search(),
        sortKey: this.sort().key,
        sortDir: this.sort().dir as SortDir,
      };
      untracked(() => this.fetch(params));
    });
  }

  private fetch(params: {
    page: number;
    size: number;
    search: string;
    sortKey: string;
    sortDir: SortDir;
  }) {
    this.loading.set(true);
    this.api.list(params).subscribe({
      next: (res) => {
        this.rows.set(res.content);
        this.total.set(res.pageable.total);
        this.loading.set(false);
        // Refresh TPE map to ensure we have latest data
        this.refreshTpeMap();
      },
      error: () => {
        this.rows.set([]);
        this.total.set(0);
        this.loading.set(false);
      },
    });
  }

  private refreshTpeMap() {
    this.tpeSvc
      .list({ page: 1, size: 200, search: '', sortKey: 'imei', sortDir: 'asc' } as any)
      .subscribe((res) => {
        const tpes = res.content as TpeDevice[];
        this.rebuildTpeMaps(tpes);
      });
  }

  private rebuildTpeMaps(tpes: TpeDevice[]) {
    this.tpeMap.clear();
    this.agentTpesMap.clear();
    tpes.forEach((t) => {
      this.tpeMap.set(t.id, t);
      const agentId = t.agent?.id;
      if (agentId) {
        const list = this.agentTpesMap.get(agentId) || [];
        list.push(t);
        this.agentTpesMap.set(agentId, list);
      }
    });
  }

  getAgentTpes(agentId: string): TpeDevice[] {
    return this.agentTpesMap.get(agentId) || [];
  }

  renderStatutBadge(statut: Agent['statut'] | string | undefined): string {
    if (!statut) return '';
    const s = String(statut).toUpperCase();
    if (s === 'ACTIF') {
      return `<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>`;
    }
    if (s === 'INACTIF') {
      return `<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>`;
    }
    return `<span class="inline-flex items-center gap-1 px-2 py-1 rounded bg-orange-500/10 text-orange-600 dark:text-orange-400 text-xs font-medium"><i class="icon-alert-circle"></i> Suspendu</span>`;
  }

  formatLimits(a: Agent): string {
    const parts: string[] = [];
    const nf = new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 });
    if (a.limiteInferieure !== undefined) parts.push(nf.format(a.limiteInferieure));
    if (a.limiteSuperieure !== undefined) parts.push(nf.format(a.limiteSuperieure));
    return parts.length ? parts.join(' — ') : '';
  }

  onSearch(q: string) {
    this.search.set(q);
    this.page.set(1);
  }
  openCreate() {
    this.modalTitle.set('Nouvel agent');
    this.editingItem.set(null);
    queueMicrotask(() => this.modalOpen.set(true));
  }
  openEdit(row: Agent) {
    this.modalTitle.set("Modifier l'agent");
    this.editingItem.set(row);
    queueMicrotask(() => this.modalOpen.set(true));
  }
  closeModal() {
    this.modalOpen.set(false);
  }
  openDetail(row: Agent) {
    // Fetch full agent details
    this.api.getById(row.id).subscribe({
      next: (agent) => {
        if (agent) {
          this.detailItem.set(agent);
          // Load family members separately
          this.familyMemberService.getByAgentId(agent.id).subscribe({
            next: (members) => {
              this.detailFamilyMembers.set(members);
            },
            error: () => {
              this.detailFamilyMembers.set([]);
            },
          });
          this.detailModalOpen.set(true);
        }
      },
      error: () => {
        // If fetch fails, use the row data
        this.detailItem.set(row);
        // Try to load family members anyway
        this.familyMemberService.getByAgentId(row.id).subscribe({
          next: (members) => {
            this.detailFamilyMembers.set(members);
          },
          error: () => {
            this.detailFamilyMembers.set([]);
          },
        });
        this.detailModalOpen.set(true);
      },
    });
  }
  closeDetailModal() {
    this.detailModalOpen.set(false);
    this.detailItem.set(null);
    this.detailFamilyMembers.set([]);
  }
  submitChildForm() {
    this.formComp?.onSubmit();
  }

  onFormSave(payload: Partial<Agent>) {
    const current = this.editingItem();
    const familyMembersData = this.formComp?.getFamilyMembersData() || [];

    // Save agent first
    const req$ = current?.id
      ? this.api.update(current.id, payload)
      : this.api.create(payload as Omit<Agent, 'id'>);

    req$
      .pipe(
        switchMap((result) => {
          if (!result && current?.id) {
            // Update failed
            throw new Error("Erreur lors de la sauvegarde de l'agent");
          }

          const savedAgentId = result?.id || current?.id || '';
          if (!savedAgentId) {
            throw new Error("Impossible d'obtenir l'ID de l'agent sauvegardé");
          }

          // Get existing family members for this agent
          return this.familyMemberService.getByAgentId(savedAgentId).pipe(
            switchMap((existingMembers) => {
              const existingIds = new Set(existingMembers.map((m) => m.id));
              const newMembers = familyMembersData.filter((fm) => !fm.id);
              const updatedMembers = familyMembersData.filter(
                (fm) => fm.id && existingIds.has(fm.id)
              );
              const deletedIds = existingMembers
                .filter((em) => !familyMembersData.some((fm) => fm.id === em.id))
                .map((em) => em.id);

              const operations: any[] = [];

              // Delete removed members
              deletedIds.forEach((id) => {
                operations.push(
                  this.familyMemberService.delete(id).pipe(
                    catchError((err) => {
                      console.error(`Error deleting family member ${id}:`, err);
                      return of(false);
                    })
                  )
                );
              });

              // Create new members
              newMembers.forEach((member) => {
                operations.push(
                  this.familyMemberService
                    .create({
                      agentId: savedAgentId,
                      nom: member.nom,
                      statut: member.statut,
                      dateNaissance: member.dateNaissance,
                      sexe: member.sexe as 'M' | 'F' | undefined,
                    })
                    .pipe(
                      catchError((err) => {
                        console.error('Error creating family member:', err);
                        return of(null);
                      })
                    )
                );
              });

              // Update existing members
              updatedMembers.forEach((member) => {
                if (member.id) {
                  operations.push(
                    this.familyMemberService
                      .update(member.id, {
                        nom: member.nom,
                        statut: member.statut,
                        dateNaissance: member.dateNaissance,
                        sexe: member.sexe as 'M' | 'F' | undefined,
                      })
                      .pipe(
                        catchError((err) => {
                          console.error(`Error updating family member ${member.id}:`, err);
                          return of(null);
                        })
                      )
                  );
                }
              });

              return operations.length > 0 ? forkJoin(operations) : of([]);
            })
          );
        })
      )
      .subscribe({
        next: () => {
          // Reset form after successful save
          this.formComp?.resetForm();
          // Clear editing item
          this.editingItem.set(null);
          // Close modal
          this.closeModal();
          // Refresh data
          this.fetch({
            page: this.page(),
            size: this.size(),
            search: this.search(),
            sortKey: this.sort().key,
            sortDir: this.sort().dir as SortDir,
          });
        },
        error: (err) => {
          console.error('Error saving agent:', err);
          alert("Erreur lors de la sauvegarde de l'agent");
        },
      });
  }

  remove(row: Agent) {
    if (!confirm(`Supprimer l\'agent ${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,
      })
    );
  }

  openAssignTpe(agent: Agent) {
    this.assigningAgent.set(agent);
    this.selectedTpeId.set('');
    this.loadAvailableTpes();
    this.assignTpeModalOpen.set(true);
  }

  loadAvailableTpes() {
    this.tpesLoading.set(true);
    const agent = this.assigningAgent();
    if (!agent) {
      this.availableTpes.set([]);
      this.tpesLoading.set(false);
      return;
    }

    const currentAgentTpes = this.agentTpesMap.get(agent.id) || [];
    const agentTpeIds = new Set(currentAgentTpes.map((t) => t.id));

    // Load available TPEs (DISPONIBLE or VALIDE status)
    forkJoin([this.tpeSvc.getByStatut('DISPONIBLE'), this.tpeSvc.getByStatut('VALIDE')]).subscribe({
      next: ([disponibleTpes, valideTpes]) => {
        // Combine and filter: only show TPEs that are not assigned to any agent AND not already assigned to this agent
        const allTpes = [...disponibleTpes, ...valideTpes];
        const available = allTpes.filter(
          (t) =>
            !t.assigne &&
            (t.statut === 'DISPONIBLE' || t.statut === 'VALIDE') &&
            !agentTpeIds.has(t.id)
        );
        // Remove duplicates
        const uniqueTpes = Array.from(new Map(available.map((t) => [t.id, t])).values());
        this.availableTpes.set(uniqueTpes);
        this.tpesLoading.set(false);
      },
      error: () => {
        this.availableTpes.set([]);
        this.tpesLoading.set(false);
      },
    });
  }

  confirmAssignTpe() {
    const agent = this.assigningAgent();
    const tpeId = this.selectedTpeId();
    if (!agent || !tpeId) {
      alert('Veuillez sélectionner un TPE');
      return;
    }

    // Assign TPE to agent
    this.tpeSvc.assigner(tpeId, agent.id).subscribe({
      next: (tpe) => {
        if (tpe) {
          // Fermer le modal et recharger complètement la page
          this.assignTpeModalOpen.set(false);
          this.assigningAgent.set(null);
          this.selectedTpeId.set('');
          // Rechargement complet pour s'assurer que la liste des agents / TPE est à jour
          window.location.reload();
        }
      },
      error: () => {
        alert("Erreur lors de l'assignation du TPE");
      },
    });
  }

  closeAssignTpeModal() {
    this.assignTpeModalOpen.set(false);
    this.assigningAgent.set(null);
    this.selectedTpeId.set('');
  }
}
