import { Logger as TypeOrmLogger, QueryRunner } from 'typeorm';
import {
    dbQueryTotal,
    dbQueryFailedTotal,
    dbQueryDuration,
} from './db-metrics';

export class TypeOrmMetricsLogger implements TypeOrmLogger {
    constructor(private readonly dbName: string) { }

    logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) {
        if (!queryRunner) return;

        (queryRunner as any).__start = Date.now();
        (queryRunner as any).__op =
            query.trim().split(' ')[0]?.toUpperCase() || 'UNKNOWN';
    }

    logQueryResult(
        query: string,
        parameters?: any[],
        queryRunner?: QueryRunner,
    ) {
        this.observe(queryRunner);
    }

    logQueryError(
        error: string | Error,
        query: string,
        parameters?: any[],
        queryRunner?: QueryRunner,
    ) {
        const job = process.env.SERVICE_NAME || 'HUB-backend';

        dbQueryTotal.inc({ job, db: this.dbName });
        dbQueryFailedTotal.inc({ job, db: this.dbName });

        this.observe(queryRunner);
    }

    logQuerySlow(
        time: number,
        query: string,
        parameters?: any[],
        queryRunner?: QueryRunner,
    ) {
        this.observe(queryRunner);
    }

    private observe(queryRunner?: QueryRunner) {
        if (!queryRunner) return;

        const start = (queryRunner as any).__start;
        if (!start) return;

        const job = process.env.SERVICE_NAME || 'HUB-backend';
        const op = (queryRunner as any).__op || 'UNKNOWN';
        const duration = (Date.now() - start) / 1000;

        dbQueryTotal.inc({ job, db: this.dbName });
        dbQueryDuration.observe(
            { job, db: this.dbName, operation: op },
            duration,
        );
    }

    // Required no-ops
    logSchemaBuild() { }
    logMigration() { }
    log(level: 'log' | 'info' | 'warn', message: any) { }
}
