import { Injectable, computed, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, Observable, tap } from 'rxjs';
import { ApiEnvelope, AuthSession, AuthUser } from '../models';

@Injectable({ providedIn: 'root' })
export class AuthService {
  private readonly apiBase = '/api/auth';

  private readonly _token = signal<string | null>(null);
  private readonly _user = signal<AuthUser | null>(null);

  readonly user = computed(() => this._user());
  readonly isAuthenticated = computed(() => Boolean(this._token() && this._user()));

  constructor(private readonly http: HttpClient) {
    this.hydrate();
  }

  private hydrate() {
    const token = localStorage.getItem('invima_token');
    const rawUser = localStorage.getItem('invima_user');
    if (!token || !rawUser) return;
    try {
      const user = JSON.parse(rawUser) as AuthUser;
      this._token.set(token);
      this._user.set(user);
    } catch {
      this.clearSession();
    }
  }

  private setSession(session: AuthSession) {
    this._token.set(session.accessToken);
    this._user.set(session.user);
    localStorage.setItem('invima_token', session.accessToken);
    localStorage.setItem('invima_user', JSON.stringify(session.user));
  }

  clearSession() {
    this._token.set(null);
    this._user.set(null);
    localStorage.removeItem('invima_token');
    localStorage.removeItem('invima_user');
  }

  getAccessToken(): string | null {
    return this._token();
  }

  login(identifier: string, password: string): Observable<AuthSession> {
    return this.http
      .post<ApiEnvelope<AuthSession>>(`${this.apiBase}/login`, { identifier, password })
      .pipe(
        map((response) => response.data),
        tap((session) => this.setSession(session))
      );
  }

  me(): Observable<AuthUser> {
    return this.http.get<ApiEnvelope<AuthUser>>(`${this.apiBase}/me`).pipe(
      map((response) => response.data),
      tap((user) => {
        this._user.set(user);
        localStorage.setItem('invima_user', JSON.stringify(user));
      })
    );
  }

  logout(): Observable<boolean> {
    return this.http.post<ApiEnvelope<unknown>>(`${this.apiBase}/logout`, {}).pipe(
      tap(() => this.clearSession()),
      map(() => true)
    );
  }
}
