import { NextFunction, Request, Response } from 'express';
import {
  requireForm1626AsAccess,
  requireForm16ReOnly,
  requireForm16SubmissionAccess,
} from '../middlewares/form16Permission.middleware';
import { canView26As, canViewForm16Submission } from '../services/form16Permission.service';
import { getDealerCodeForUser } from '../services/form16.service';

jest.mock('../services/form16Permission.service', () => ({
  canView26As: jest.fn(),
  canViewForm16Submission: jest.fn(),
}));

jest.mock('../services/form16.service', () => ({
  getDealerCodeForUser: jest.fn(),
}));

function createRes(): Response {
  const res: Partial<Response> = {};
  res.status = jest.fn().mockReturnValue(res);
  res.json = jest.fn().mockReturnValue(res);
  return res as Response;
}

describe('Form16 Permission Middlewares', () => {
  const mockedCanView26As = canView26As as jest.Mock;
  const mockedCanViewForm16Submission = canViewForm16Submission as jest.Mock;
  const mockedGetDealerCodeForUser = getDealerCodeForUser as jest.Mock;

  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('allows ADMIN on 26AS middleware without config dependency', async () => {
    const req = { user: { userId: 'a1', email: 'admin@royalenfield.com', role: 'ADMIN' } } as unknown as Request;
    const res = createRes();
    const next = jest.fn() as NextFunction;

    await requireForm1626AsAccess(req, res, next);

    expect(next).toHaveBeenCalledTimes(1);
    expect(mockedCanView26As).not.toHaveBeenCalled();
  });

  it('denies non-authorized user on 26AS middleware', async () => {
    mockedCanView26As.mockResolvedValue(false);
    const req = { user: { userId: 'u1', email: 'user@royalenfield.com', role: 'USER' } } as unknown as Request;
    const res = createRes();
    const next = jest.fn() as NextFunction;

    await requireForm1626AsAccess(req, res, next);

    expect(next).not.toHaveBeenCalled();
    expect((res.status as jest.Mock).mock.calls[0][0]).toBe(403);
  });

  it('denies dealer on RE-only middleware', async () => {
    mockedGetDealerCodeForUser.mockResolvedValue('DLR001');
    const req = { user: { userId: 'u2', email: 'dealer@royalenfield.com', role: 'USER' } } as unknown as Request;
    const res = createRes();
    const next = jest.fn() as NextFunction;

    await requireForm16ReOnly(req, res, next);

    expect(next).not.toHaveBeenCalled();
    expect((res.status as jest.Mock).mock.calls[0][0]).toBe(403);
  });

  it('allows submission middleware for authorized non-admin RE user', async () => {
    mockedCanViewForm16Submission.mockResolvedValue(true);
    const req = { user: { userId: 'u3', email: 'submission@royalenfield.com', role: 'USER' } } as unknown as Request;
    const res = createRes();
    const next = jest.fn() as NextFunction;

    await requireForm16SubmissionAccess(req, res, next);

    expect(next).toHaveBeenCalledTimes(1);
  });
});
