import { Injectable, inject, signal } from '@angular/core';
import { take } from 'rxjs/operators';
import { AdminInvitation, AdminUserRoleRecord, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
import { ADMIN_USERS_GATEWAY } from '../services/admin-users-gateway.token';

@Injectable({ providedIn: 'root' })
export class AdminUsersFacade {
  private readonly gateway = inject(ADMIN_USERS_GATEWAY);

  readonly users = signal<AdminUser[]>([]);
  readonly roles = signal<AdminUserRoleRecord[]>([]);
  readonly invitations = signal<AdminInvitation[]>([]);
  readonly loading = signal(false);
  readonly error = signal(false);
  readonly mutationError = signal<string | null>(null);
  readonly sessionsTarget = signal<AdminUser | null>(null);
  readonly sessions = signal<AdminSession[]>([]);
  readonly auditTarget = signal<AdminUser | null>(null);
  readonly audit = signal<AdminUserAuditEntry[]>([]);

  loadAll(): void {
    this.loading.set(true);
    this.error.set(false);
    this.gateway.loadUsers().pipe(take(1)).subscribe({
      next: users => { this.users.set(users); this.loading.set(false); },
      error: () => { this.users.set([]); this.loading.set(false); this.error.set(true); }
    });
    this.gateway.loadRoles().pipe(take(1)).subscribe(roles => this.roles.set(roles));
    this.gateway.loadInvitations().pipe(take(1)).subscribe(invitations => this.invitations.set(invitations));
  }

  roleName(roleId: string): string {
    return this.roles().find(role => role.id === roleId)?.name ?? roleId;
  }

  setRole(userId: string, roleId: string): void {
    this.mutationError.set(null);
    this.gateway.setUserRole(userId, roleId).pipe(take(1)).subscribe({
      next: () => this.loadAll(),
      error: () => this.mutationError.set('common.errorDescription')
    });
  }

  setStatus(userId: string, status: AdminUserStatus): void {
    this.mutationError.set(null);
    this.gateway.setUserStatus(userId, status).pipe(take(1)).subscribe({
      next: () => this.loadAll(),
      error: () => this.mutationError.set('common.errorDescription')
    });
  }

  invite(email: string, roleId: string, scope: AdminUserScope): void {
    if (!email.trim()) return;
    this.mutationError.set(null);
    this.gateway.inviteUser(email.trim(), roleId, scope).pipe(take(1)).subscribe({
      next: () => this.loadAll(),
      error: () => this.mutationError.set('common.errorDescription')
    });
  }

  revokeInvitation(id: string): void {
    this.gateway.revokeInvitation(id).pipe(take(1)).subscribe({ next: () => this.loadAll() });
  }

  openSessions(user: AdminUser): void {
    this.sessionsTarget.set(user);
    this.gateway.loadSessions(user.id).pipe(take(1)).subscribe(sessions => this.sessions.set(sessions));
  }

  closeSessions(): void {
    this.sessionsTarget.set(null);
  }

  revokeSession(sessionId: string): void {
    this.gateway.revokeSession(sessionId).pipe(take(1)).subscribe({
      next: () => {
        const user = this.sessionsTarget();
        if (user) this.openSessions(user);
      }
    });
  }

  openAudit(user: AdminUser): void {
    this.auditTarget.set(user);
    this.gateway.loadAudit(user.id).pipe(take(1)).subscribe(entries => this.audit.set(entries));
  }

  closeAudit(): void {
    this.auditTarget.set(null);
  }
}
