import { RuleTester } from 'eslint';
import test from 'node:test';
import rule from '../../src/eslint/rules/no-silent-catch-return.js';

const ruleTester = new RuleTester({
  languageOptions: {
    ecmaVersion: 2022,
    sourceType: 'module',
  },
});

const wrap = (body: string): string => `async function handler() { ${body} }`;

test('no-silent-catch-return', () => {
  ruleTester.run('no-silent-catch-return', rule, {
    valid: [
      {
        name: 'catch with logger before null return',
        code: wrap(`
          try { foo(); } catch (e) {
            logger.warn('foo failed', { error: e });
            return null;
          }
        `),
      },
      {
        name: 'catch that rethrows',
        code: wrap(`
          try { foo(); } catch (e) {
            throw new HttpErrors.BadRequestError('oops');
          }
        `),
      },
      {
        name: 'catch that returns a non-empty object',
        code: wrap(`
          try { foo(); } catch (e) {
            return { error: e.message };
          }
        `),
      },
      {
        name: 'catch with no return',
        code: wrap(`
          try { foo(); } catch (e) {
            doSomething();
          }
        `),
      },
      {
        name: 'catch with console + return',
        code: wrap(`
          try { foo(); } catch (e) {
            console.error('oops', e);
            return [];
          }
        `),
      },
      {
        name: 'catch with chained context.logger.warn',
        code: wrap(`
          try { foo(); } catch (e) {
            context.logger.warn('failed', { error: e });
            return [];
          }
        `),
      },
      {
        name: 'catch with awaited logger call',
        code: wrap(`
          try { foo(); } catch (e) {
            await logger.error('boom');
            return null;
          }
        `),
      },
      {
        name: 'catch with deeply nested service.logger.warn',
        code: wrap(`
          try { foo(); } catch (e) {
            this.context.logger.warn('failed');
            return null;
          }
        `),
      },
    ],
    invalid: [
      {
        name: 'silent return null',
        code: wrap(`
          try { foo(); } catch (e) {
            return null;
          }
        `),
        errors: [{ messageId: 'silentReturn', data: { value: 'null' } }],
      },
      {
        name: 'silent return undefined identifier',
        code: wrap(`
          try { foo(); } catch (e) {
            return undefined;
          }
        `),
        errors: [{ messageId: 'silentReturn', data: { value: 'undefined' } }],
      },
      {
        name: 'silent bare return',
        code: wrap(`
          try { foo(); } catch (e) {
            return;
          }
        `),
        errors: [{ messageId: 'silentReturn', data: { value: 'undefined' } }],
      },
      {
        name: 'silent return empty array',
        code: wrap(`
          try { foo(); } catch (e) {
            return [];
          }
        `),
        errors: [{ messageId: 'silentReturn', data: { value: '[]' } }],
      },
      {
        name: 'silent return empty object',
        code: wrap(`
          try { foo(); } catch (e) {
            return {};
          }
        `),
        errors: [{ messageId: 'silentReturn', data: { value: '{}' } }],
      },
      {
        name: 'silent return empty string',
        code: wrap(`
          try { foo(); } catch (e) {
            return '';
          }
        `),
        errors: [{ messageId: 'silentReturn', data: { value: '' } }],
      },
    ],
  });
});
