import { Injectable } from '@angular/core';

interface StoredAuthToken {
  token: string;
  expiresAt: number;
}

const STORAGE_KEY = 'metoyou.authTokens';

@Injectable({ providedIn: 'root' })
export class AuthTokenStoreService {
  setToken(serverUrl: string, token: string, expiresAt: number): void {
    const normalizedUrl = this.normalizeServerUrl(serverUrl);
    const store = this.readStore();

    store[normalizedUrl] = { token, expiresAt };
    this.writeStore(store);
  }

  getToken(serverUrl: string): string | null {
    const entry = this.getTokenEntry(serverUrl);

    return entry?.token ?? null;
  }

  getTokenEntry(serverUrl: string): StoredAuthToken | null {
    const normalizedUrl = this.normalizeServerUrl(serverUrl);
    const entry = this.readStore()[normalizedUrl];

    if (!entry) {
      return null;
    }

    if (entry.expiresAt <= Date.now()) {
      this.clearToken(serverUrl);
      return null;
    }

    return entry;
  }

  clearToken(serverUrl: string): void {
    const normalizedUrl = this.normalizeServerUrl(serverUrl);
    const store = this.readStore();
    const nextStore = Object.fromEntries(
      Object.entries(store).filter(([key]) => key !== normalizedUrl)
    ) as Record<string, StoredAuthToken>;

    this.writeStore(nextStore);
  }

  hasAnyValidToken(): boolean {
    const now = Date.now();

    return Object.values(this.readStore()).some((entry) => entry.expiresAt > now);
  }

  findTokenForApiUrl(apiUrl: string): string | null {
    const normalizedApiUrl = apiUrl.trim().replace(/\/+$/, '');

    for (const [serverUrl, entry] of Object.entries(this.readStore())) {
      if (entry.expiresAt <= Date.now()) {
        continue;
      }

      if (normalizedApiUrl === serverUrl || normalizedApiUrl.startsWith(`${serverUrl}/`)) {
        return entry.token;
      }
    }

    return null;
  }

  private readStore(): Record<string, StoredAuthToken> {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);

      if (!raw) {
        return {};
      }

      const parsed = JSON.parse(raw) as Record<string, StoredAuthToken>;

      return parsed && typeof parsed === 'object' ? parsed : {};
    } catch {
      return {};
    }
  }

  private writeStore(store: Record<string, StoredAuthToken>): void {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(store));
  }

  private normalizeServerUrl(serverUrl: string): string {
    return serverUrl.trim().replace(/\/+$/, '');
  }
}
