import { localDataSource } from '../LocalDataSource';
import type { ILocalDataSource } from '@/data/datasources/interfaces';
import type { UserDTO } from '@/types/dto';
import { safeParseJson } from '../core/jsonUtils';

export interface IUserCacheRepository {
  save(user: UserDTO): Promise<void>;
  saveBatch(users: UserDTO[]): Promise<void>;
  get(userId: string): Promise<UserDTO | null>;
  getLatest(): Promise<UserDTO | null>;
  saveCurrent(user: UserDTO): Promise<void>;
  getCurrent(): Promise<UserDTO | null>;
  clearCurrent(): Promise<void>;
}

export class UserCacheRepository implements IUserCacheRepository {
  constructor(private dataSource: ILocalDataSource = localDataSource) {}

  async save(user: UserDTO): Promise<void> {
    await this.dataSource.enqueueWrite(async () => {
      await this.dataSource.run(
        `INSERT OR REPLACE INTO users (id, data, updatedAt) VALUES (?, ?, ?)`,
        [String(user.id), JSON.stringify(user), new Date().toISOString()]
      );
    });
  }

  async saveBatch(users: UserDTO[]): Promise<void> {
    if (!users?.length) return;
    await this.dataSource.enqueueWrite(async () => {
      const now = new Date().toISOString();
      for (const u of users) {
        await this.dataSource.run(
          `INSERT OR REPLACE INTO users (id, data, updatedAt) VALUES (?, ?, ?)`,
          [String(u.id), JSON.stringify(u), now]
        );
      }
    });
  }

  async get(userId: string): Promise<UserDTO | null> {
    const r = await this.dataSource.getFirst<{ data: string }>(
      `SELECT data FROM users WHERE id = ?`, [String(userId)]
    );
    return r?.data ? safeParseJson<UserDTO>(r.data) : null;
  }

  async getLatest(): Promise<UserDTO | null> {
    const r = await this.dataSource.getFirst<{ data: string }>(
      `SELECT data FROM users ORDER BY updatedAt DESC LIMIT 1`
    );
    return r?.data ? safeParseJson<UserDTO>(r.data) : null;
  }

  async saveCurrent(user: UserDTO): Promise<void> {
    await this.dataSource.enqueueWrite(async () => {
      await this.dataSource.run(
        `INSERT OR REPLACE INTO current_user_cache (id, data, updatedAt) VALUES (?, ?, ?)`,
        ['me', JSON.stringify(user), new Date().toISOString()]
      );
    });
  }

  async getCurrent(): Promise<UserDTO | null> {
    const r = await this.dataSource.getFirst<{ data: string }>(
      `SELECT data FROM current_user_cache WHERE id = 'me'`
    );
    return r?.data ? safeParseJson<UserDTO>(r.data) : null;
  }

  async clearCurrent(): Promise<void> {
    await this.dataSource.enqueueWrite(async () => {
      await this.dataSource.run(`DELETE FROM current_user_cache WHERE id = 'me'`);
    });
  }
}

export const userCacheRepository = new UserCacheRepository();