import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, BehaviorSubject, tap, catchError, throwError } from 'rxjs'; // <-- AGREGAR catchError y throwError
import { Router } from '@angular/router';

export interface User {
  id_usuario: number;
  username: string;
  nombre_completo: string;
  nombre_rol: string;
  sedes?: Array<{
    codigo_establecimiento: string;
    nombre_establecimiento: string;
  }>;
}

export interface LoginRequest {
  username: string;
  password: string;
}

export interface LoginResponse {
  token: string;
  usuario: User;
}

export interface RegisterRequest {
  username: string;
  email: string;
  password: string;
  nombre_completo: string;
  id_rol: number;
  sedes?: string[]; // Array de códigos de establecimiento
}

export interface Rol {
  id_rol: number;
  nombre_rol: string;
  descripcion?: string;
}

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private readonly API_URL = 'http://localhost:3000';
  private readonly TOKEN_KEY = 'auth_token';
  private readonly USER_KEY = 'current_user';

  private currentUserSubject = new BehaviorSubject<User | null>(null);
  public currentUser$ = this.currentUserSubject.asObservable();

  private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
  public isAuthenticated$ = this.isAuthenticatedSubject.asObservable();

  constructor(
    private http: HttpClient,
    private router: Router
  ) {
    this.initializeAuth();
  }

  private initializeAuth(): void {
    const token = this.getToken();
    const user = this.getUserFromStorage();

    if (token && user) {
      this.currentUserSubject.next(user);
      this.isAuthenticatedSubject.next(true);
    } else {
      this.clearAuth();
    }
  }

  login(credentials: LoginRequest): Observable<LoginResponse> {
    console.log('Enviando login:', credentials); // Log para depuración
    
    return this.http.post<LoginResponse>(`${this.API_URL}/api/auth/login`, credentials).pipe(
      tap(response => {
        console.log('Respuesta del servidor:', response); // Log para depuración
        this.setAuth(response.token, response.usuario);
      }),
      catchError((error: any) => { // <-- Agregar tipo any al error
        console.error('Error en login:', error); // Log para depuración
        return throwError(() => error); // <-- Usar throwError correctamente
      })
    );
  }

  register(userData: RegisterRequest): Observable<any> {
    const headers = this.getAuthHeaders();
    return this.http.post(`${this.API_URL}/api/auth/register`, userData);
  }

  logout(): void {
    this.http.post(`${this.API_URL}/api/auth/logout`, {}).subscribe({
      next: () => {
        this.clearAuth();
        this.router.navigate(['/login']);
      },
      error: () => {
        // Even if API call fails, clear local auth
        this.clearAuth();
        this.router.navigate(['/login']);
      }
    });
  }

  verifyToken(): Observable<{ usuario: User }> {
    const headers = this.getAuthHeaders();
    return this.http.get<{ usuario: User }>(`${this.API_URL}/api/auth/verify`, { headers }).pipe(
      tap(response => {
        this.updateUser(response.usuario);
      })
    );
  }

  getToken(): string | null {
    return localStorage.getItem(this.TOKEN_KEY);
  }

  private setAuth(token: string, user: User): void {
    localStorage.setItem(this.TOKEN_KEY, token);
    localStorage.setItem(this.USER_KEY, JSON.stringify(user));
    this.currentUserSubject.next(user);
    this.isAuthenticatedSubject.next(true);
  }

  private clearAuth(): void {
    localStorage.removeItem(this.TOKEN_KEY);
    localStorage.removeItem(this.USER_KEY);
    this.currentUserSubject.next(null);
    this.isAuthenticatedSubject.next(false);
  }

  private updateUser(user: User): void {
    localStorage.setItem(this.USER_KEY, JSON.stringify(user));
    this.currentUserSubject.next(user);
  }

  private getUserFromStorage(): User | null {
    const userStr = localStorage.getItem(this.USER_KEY);
    return userStr ? JSON.parse(userStr) : null;
  }

    // Obtener lista de roles (solo admin)
  getRoles(): Observable<Rol[]> {
    const headers = this.getAuthHeaders();
    return this.http.get<Rol[]>(`${this.API_URL}/api/roles`, { headers });
  }

  // Activar / desactivar usuario (solo admin)
  actualizarEstadoUsuario(idUsuario: number, activo: boolean): Observable<any> {
    const headers = this.getAuthHeaders().set('Content-Type', 'application/json');
    return this.http.patch(
      `${this.API_URL}/api/usuarios/${idUsuario}/estado`,
      { activo },
      { headers }
    );
  }

  // Por comodidad, un helper
  puedeGestionarUsuarios(): boolean {
    return this.isAdministrador();
  }


  getAuthHeaders(): HttpHeaders {
  const token = this.getToken();
  let headers = new HttpHeaders();

  // ❌ NO ponemos Content-Type aquí.
  // Angular se encarga:
  //  - Si el body es un objeto → application/json
  //  - Si el body es FormData → multipart/form-data con boundary

  if (token) {
    headers = headers.set('Authorization', `Bearer ${token}`);
  }

  return headers;
}


  getCurrentUser(): User | null {
    return this.currentUserSubject.value;
  }

  isLoggedIn(): boolean {
    return this.isAuthenticatedSubject.value;
  }

  hasRole(role: string): boolean {
    const user = this.getCurrentUser();
    return user ? user.nombre_rol === role : false;
  }

  isAdministrador(): boolean {
    return this.hasRole('administrador');
  }

  isAdministrativoSede(): boolean {
    return this.hasRole('administrativo_sede');
  }

  puedeCargarPacientes(): boolean {
    return this.isAdministrador();
  }

  puedeDescargarPdfs(): boolean {
    return this.isAdministrador();
  }

  puedeVerTodasAutorizaciones(): boolean {
    return this.isAdministrador();
  }

  puedeGenerarAutorizaciones(): boolean {
    const user = this.getCurrentUser();
    return user ? (user.nombre_rol === 'administrador' || user.nombre_rol === 'administrativo_sede') : false;
  }

  tieneAccesoAEstablecimiento(codigoEstablecimiento: string): boolean {
    const user = this.getCurrentUser();
    if (!user) return false;

    // Los administradores tienen acceso a todos los establecimientos
    if (user.nombre_rol === 'administrador') return true;

    // Los administrativos solo tienen acceso a sus sedes asignadas
    if (user.nombre_rol === 'administrativo_sede' && user.sedes) {
      return user.sedes.some(sede => sede.codigo_establecimiento === codigoEstablecimiento);
    }

    return false;
  }

  // Obtener lista de usuarios (solo administradores)
  getUsuarios(): Observable<any[]> {
    const headers = this.getAuthHeaders();
    return this.http.get<any[]>(`${this.API_URL}/api/usuarios`, { headers });
  }

  // Obtener autorizaciones por fecha (solo administradores)
  getAutorizacionesPorFecha(fechaInicio: string, fechaFin: string): Observable<any[]> {
    const headers = this.getAuthHeaders();
    const params = { fecha_inicio: fechaInicio, fecha_fin: fechaFin };
    return this.http.get<any[]>(`${this.API_URL}/api/autorizaciones-por-fecha`, { headers, params });
  }
}