import { Injectable } from '@angular/core';
import { StorageUser } from '../../types/type.user';
import { CryptoService } from './crypto.service';

@Injectable({
  providedIn: 'root',
})
export class StorageService {
  private readonly secret = 'precaution-check2-secret';
  private readonly prefix = 'precaution-check2-client';

  _cacheToken?: string;
  constructor(private readonly crypto: CryptoService) {}

  set token(value: string) {
    this._cacheToken = value;
    this.setString('token', value);
  }

  get token(): string | undefined {
    if (this._cacheToken) {
      return this._cacheToken;
    }
    const token = this.getString('token');
    if (!token) {
      return undefined;
    }
    this._cacheToken = token;
    return token;
  }
  clearToken() {
    this._cacheToken = undefined;
    this.setString('token', '');
  }
  remove(key: string) {
    localStorage.removeItem(this.getRealKey(key));
  }
  setString(key: string, data: string): void {
    key = this.getRealKey(key);
    if (!data || data.length <= 0) {
      localStorage.removeItem(key);
    }
    const result = this.crypto.aesEncrypt(data, this.secret);
    localStorage.setItem(key, result);
  }

  getString(key: string): string | undefined {
    key = this.getRealKey(key);
    const result = localStorage.getItem(key);
    if (!result) {
      return undefined;
    }
    try {
      return this.crypto.aesDecrypt(result, this.secret);
    } catch (err) {
      console.error('decrypt error', err);
      return undefined;
    }
  }

  setNumber(key: string, data: number): void {
    return this.setString(key, String(data));
  }

  getNumber(key: string): number | undefined {
    const result = this.getString(key);
    return Number(result) ?? undefined;
  }

  setBoolean(key: string, data: boolean): void {
    key = this.getRealKey(key);
    if (data) {
      localStorage.setItem(key, '1');
    } else {
      localStorage.removeItem(key);
    }
  }

  getBoolean(key: string): boolean {
    key = this.getRealKey(key);
    const item = localStorage.getItem(key);
    return item != undefined;
  }

  private getRealKey(key: string) {
    return `${this.prefix}-${key}`;
  }

  public addUser(user: StorageUser) {
    let users = this.getUsers().filter(i => i.id != user.id);
    users = [user].concat(...users);
    this.setData('userList', users);
  }

  public getUsers(): StorageUser[] {
    return this.getData<StorageUser[]>('userList') ?? [];
  }

  public removeUser(id: string) {
    const users = this.getUsers().filter(i => i.id != id);
    this.setData('userList', users);
  }

  setData<T>(key: string, data: T): void {
    if (!data) {
      key = this.getRealKey(key);
      localStorage.removeItem(key);
      return;
    }
    const json = JSON.stringify(data);
    this.setString(key, json);
  }

  getData<T>(key: string): T | undefined {
    const json = this.getString(key);
    if (!json) {
      return undefined;
    }
    return JSON.parse(json) as T;
  }
}
