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

export interface IGroupCacheRepository {
  save(group: GroupResponse): Promise<void>;
  saveBatch(groups: GroupResponse[]): Promise<void>;
  get(groupId: string): Promise<GroupResponse | null>;
  getAll(): Promise<GroupResponse[]>;
  saveMembers(groupId: string, members: GroupMemberResponse[]): Promise<void>;
  getMembers(groupId: string): Promise<GroupMemberResponse[]>;
}

export class GroupCacheRepository implements IGroupCacheRepository {
  constructor(private dataSource: ILocalDataSource = localDataSource) {}

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

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

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

  async getAll(): Promise<GroupResponse[]> {
    const rows = await this.dataSource.query<{ data: string }>(
      `SELECT data FROM groups ORDER BY updatedAt DESC`
    );
    return rows.map(r => safeParseJson<GroupResponse>(r.data)).filter((g): g is GroupResponse => Boolean(g));
  }

  async saveMembers(groupId: string, members: GroupMemberResponse[]): Promise<void> {
    await this.dataSource.enqueueWrite(async () => {
      const now = new Date().toISOString();
      await this.dataSource.run(`DELETE FROM group_members WHERE groupId = ?`, [String(groupId)]);
      for (const m of members) {
        await this.dataSource.run(
          `INSERT OR REPLACE INTO group_members (groupId, userId, data, updatedAt) VALUES (?, ?, ?, ?)`,
          [String(groupId), String(m.user_id), JSON.stringify(m), now]
        );
      }
    });
  }

  async getMembers(groupId: string): Promise<GroupMemberResponse[]> {
    const rows = await this.dataSource.query<{ data: string }>(
      `SELECT data FROM group_members WHERE groupId = ? ORDER BY updatedAt DESC`, [String(groupId)]
    );
    return rows.map(r => safeParseJson<GroupMemberResponse>(r.data)).filter((m): m is GroupMemberResponse => Boolean(m));
  }
}

export const groupCacheRepository = new GroupCacheRepository();