import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { TenantAwareRepository } from '@it0/database';
import { AuditLog } from '../../domain/entities/audit-log.entity';

export interface AuditLogFilters {
  actionType?: string;
  actorType?: string;
  actorId?: string;
  resourceType?: string;
  from?: string;
  to?: string;
  page?: number;
  limit?: number;
}

@Injectable()
export class AuditLogRepository extends TenantAwareRepository<AuditLog> {
  constructor(dataSource: DataSource) {
    super(dataSource, AuditLog);
  }

  async queryLogs(filters: AuditLogFilters): Promise<{ data: AuditLog[]; total: number }> {
    return this.withRepository(async (repo) => {
      const qb = repo.createQueryBuilder('log');

      if (filters.actionType) {
        qb.andWhere('log.actionType = :actionType', { actionType: filters.actionType });
      }

      if (filters.actorType) {
        qb.andWhere('log.actorType = :actorType', { actorType: filters.actorType });
      }

      if (filters.actorId) {
        qb.andWhere('log.actorId = :actorId', { actorId: filters.actorId });
      }

      if (filters.resourceType) {
        qb.andWhere('log.resourceType = :resourceType', { resourceType: filters.resourceType });
      }

      if (filters.from) {
        qb.andWhere('log.createdAt >= :from', { from: new Date(filters.from) });
      }

      if (filters.to) {
        qb.andWhere('log.createdAt <= :to', { to: new Date(filters.to) });
      }

      qb.orderBy('log.createdAt', 'DESC');

      const page = filters.page ?? 1;
      const limit = filters.limit ?? 50;
      qb.skip((page - 1) * limit).take(limit);

      const [data, total] = await qb.getManyAndCount();
      return { data, total };
    });
  }

  async exportLogs(format: 'json' | 'csv'): Promise<AuditLog[] | string> {
    return this.withRepository(async (repo) => {
      const logs = await repo.find({ order: { createdAt: 'DESC' } as any });

      if (format === 'csv') {
        const headers = ['id', 'tenantId', 'actionType', 'actorType', 'actorId', 'resourceType', 'resourceId', 'ipAddress', 'createdAt'];
        const rows = logs.map(log =>
          headers.map(h => {
            const value = (log as any)[h];
            return value !== undefined && value !== null ? String(value) : '';
          }).join(','),
        );
        return [headers.join(','), ...rows].join('\n');
      }

      return logs;
    });
  }
}
