import { Injectable, Logger } from '@nestjs/common';
import { Types } from 'mongoose';
import { ModelsService } from 'src/models/models.service';

type Actor = { _id?: any; name?: string | null } | null | undefined;
type Translate = (key: string, params?: Record<string, string>) => string;

const TIMELINE_LIMIT = 200;

/** Audit trail for staff and agents, stored in the `activity-logs` collection. */
@Injectable()
export class ActivityService {
    private readonly logger = new Logger(ActivityService.name);

    constructor(private readonly models: ModelsService) { }

    /** Best effort: a failed log entry must never fail the action it describes. */
    async logMany(subjectId: any, entries: { action: string; meta?: Record<string, any> | null }[], actor?: Actor) {
        if (!entries.length) return;
        try {
            const now = +new Date();
            await this.models.ActivityLogModel.insertMany(entries.map((e, i) => ({
                subject_id: new Types.ObjectId(subjectId),
                action: e.action,
                actor_id: actor?._id ?? null,
                actor_name: actor?.name ?? null,
                meta: e.meta ?? null,
                created_at: now + i // keeps the order of entries logged together
            })));
        } catch (error) {
            this.logger.error(`Failed to write activity log for ${subjectId}`, error.stack);
        }
    }

    log(subjectId: any, action: string, actor?: Actor, meta?: Record<string, any> | null) {
        return this.logMany(subjectId, [{ action, meta }], actor);
    }

    /** Newest first, with each message translated through `translate` (keys ACTIVITY_<action>). */
    async timeline(subjectId: any, translate: Translate) {
        const logs = await this.models.ActivityLogModel
            .find({ subject_id: new Types.ObjectId(subjectId) })
            .sort({ created_at: -1, _id: -1 })
            .limit(TIMELINE_LIMIT)
            .lean();

        return logs.map(l => ({
            action: l.action,
            message: translate(`ACTIVITY_${l.action}`, {
                actor: l.actor_name || '',
                role: l.meta?.role ? translate(`ROLE_${l.meta.role}`) : '',
                reason: l.meta?.reason || ''
            }),
            actor_id: l.actor_id,
            actor_name: l.actor_name,
            created_at: l.created_at
        }));
    }
}
