import { Injectable } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';

export interface SegmentInfo {
  segmentKey: string;
  memberCount: number;
  syncedAt: Date | null;
}

@Injectable()
export class SegmentRepository {
  constructor(@InjectDataSource() private readonly ds: DataSource) {}

  async listSegments(): Promise<SegmentInfo[]> {
    const rows = await this.ds.query(
      `SELECT segment_key, COUNT(*)::int AS member_count, MAX(synced_at) AS synced_at
       FROM public.notification_segment_members
       GROUP BY segment_key
       ORDER BY segment_key`,
    );
    return rows.map((r: any) => ({
      segmentKey: r.segment_key,
      memberCount: r.member_count,
      syncedAt: r.synced_at,
    }));
  }

  async getSegmentMembers(
    segmentKey: string,
    limit = 100,
    offset = 0,
  ): Promise<{ items: { tenantId: string; syncedAt: Date }[]; total: number }> {
    const [rows, count] = await Promise.all([
      this.ds.query(
        `SELECT tenant_id, synced_at FROM public.notification_segment_members
         WHERE segment_key = $1 ORDER BY synced_at DESC LIMIT $2 OFFSET $3`,
        [segmentKey, limit, offset],
      ),
      this.ds.query(
        `SELECT COUNT(*)::int AS total FROM public.notification_segment_members WHERE segment_key = $1`,
        [segmentKey],
      ),
    ]);
    return {
      items: rows.map((r: any) => ({ tenantId: r.tenant_id, syncedAt: r.synced_at })),
      total: count[0]?.total ?? 0,
    };
  }

  /** Bulk upsert: replace the entire segment membership */
  async syncSegment(segmentKey: string, tenantIds: string[]): Promise<void> {
    await this.ds.query(
      `DELETE FROM public.notification_segment_members WHERE segment_key = $1`,
      [segmentKey],
    );
    if (tenantIds.length === 0) return;
    // Batch insert using VALUES
    const values = tenantIds.map((tid, i) => `($1, $${i + 2}, NOW())`).join(', ');
    await this.ds.query(
      `INSERT INTO public.notification_segment_members (segment_key, tenant_id, synced_at)
       VALUES ${values} ON CONFLICT DO NOTHING`,
      [segmentKey, ...tenantIds],
    );
  }

  /** Incremental add/remove */
  async addToSegment(segmentKey: string, tenantIds: string[]): Promise<void> {
    for (const tid of tenantIds) {
      await this.ds.query(
        `INSERT INTO public.notification_segment_members (segment_key, tenant_id)
         VALUES ($1, $2) ON CONFLICT DO NOTHING`,
        [segmentKey, tid],
      );
    }
  }

  async removeFromSegment(segmentKey: string, tenantIds: string[]): Promise<void> {
    if (!tenantIds.length) return;
    await this.ds.query(
      `DELETE FROM public.notification_segment_members
       WHERE segment_key = $1 AND tenant_id = ANY($2::text[])`,
      [segmentKey, tenantIds],
    );
  }

  async deleteSegment(segmentKey: string): Promise<void> {
    await this.ds.query(
      `DELETE FROM public.notification_segment_members WHERE segment_key = $1`,
      [segmentKey],
    );
  }
}
