import { Injectable } from '@nestjs/common';
import { and, eq, inArray } from 'drizzle-orm';
import { DatabaseService } from '../../common/database/database.service';
import { appState, managedAccountShares, users } from '../../database/schema';

export type SharedModule = 'trading' | 'portfolio';

@Injectable()
export class AccountSharingRepository {
  constructor(private readonly database: DatabaseService) {}

  listUsers() {
    return this.database.db
      .select({
        id: users.id,
        email: users.email,
        displayName: users.displayName,
        role: users.role,
        isActive: users.isActive,
      })
      .from(users);
  }

  listUsersByIds(ids: string[]) {
    if (!ids.length) return Promise.resolve([]);
    return this.database.db
      .select({
        id: users.id,
        email: users.email,
        displayName: users.displayName,
        role: users.role,
        isActive: users.isActive,
      })
      .from(users)
      .where(inArray(users.id, ids));
  }

  listSourceStates() {
    return this.database.db
      .select({ ownerId: appState.ownerId, key: appState.key, value: appState.value })
      .from(appState)
      .where(inArray(appState.key, [
        'ck_trading_terminal_v10_30_live',
        'ck_portfolio_terminal_v6',
      ]));
  }

  listSourceStatesFor(ownerIds: string[], key: string) {
    if (!ownerIds.length) return Promise.resolve([]);
    return this.database.db
      .select({ ownerId: appState.ownerId, key: appState.key, value: appState.value })
      .from(appState)
      .where(and(inArray(appState.ownerId, ownerIds), eq(appState.key, key)));
  }

  listShares() {
    return this.database.db.select().from(managedAccountShares);
  }

  listSharesFor(granteeId: string, module: SharedModule) {
    return this.database.db
      .select()
      .from(managedAccountShares)
      .where(and(
        eq(managedAccountShares.granteeId, granteeId),
        eq(managedAccountShares.module, module),
      ));
  }

  async create(input: {
    module: SharedModule;
    sourceOwnerId: string;
    sourceAccountId: string;
    granteeId: string;
    createdBy: string;
  }) {
    const [row] = await this.database.db
      .insert(managedAccountShares)
      .values(input)
      .onConflictDoUpdate({
        target: [
          managedAccountShares.module,
          managedAccountShares.sourceOwnerId,
          managedAccountShares.sourceAccountId,
          managedAccountShares.granteeId,
        ],
        set: { updatedAt: new Date() },
      })
      .returning();
    return row;
  }

  async delete(id: string): Promise<boolean> {
    const rows = await this.database.db
      .delete(managedAccountShares)
      .where(eq(managedAccountShares.id, id))
      .returning({ id: managedAccountShares.id });
    return rows.length > 0;
  }
}
