import express from 'express';
import request from 'supertest';
import bodyParser from 'body-parser';
import axios from 'axios';
import { generateToken } from '../auth';
import { resetMemoryStorage } from '../storage/memory';
import qrRouter from '../routes/qrRoutes';

jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;

function buildApp() {
    const app = express();
    app.use(bodyParser.json());
    app.use('/api/qr', qrRouter);
    app.use((err: any, _req: any, res: any, _next: any) => {
        res.status(400).json({ error: err.message });
    });
    return app;
}

const TOKEN = `Bearer ${generateToken('kreator')}`;

beforeEach(() => {
    resetMemoryStorage();
    mockedAxios.get = jest.fn().mockResolvedValue({ data: Buffer.from('fake-png') });
});

const VALID_BODY = {
    recipients: [
        { login: 'uzivatel1', purpose: 'Pizza Margherita', amount: 149 },
        { login: 'uzivatel2', purpose: 'Pizza Diavola', amount: 179 },
    ],
    bankAccount: '19-2000145399/0800',
    bankAccountHolder: 'Jan Novák',
};

test('POST /generate vrátí 200 s počtem vygenerovaných QR kódů', async () => {
    const res = await request(buildApp())
        .post('/api/qr/generate')
        .set('Authorization', TOKEN)
        .send(VALID_BODY);
    expect(res.status).toBe(200);
    expect(res.body.count).toBe(2);
});

test('POST /generate vrátí 400 pro prázdné recipients', async () => {
    const res = await request(buildApp())
        .post('/api/qr/generate')
        .set('Authorization', TOKEN)
        .send({ ...VALID_BODY, recipients: [] });
    expect(res.status).toBe(400);
    expect(res.body.error).toContain('příjemců');
});

test('POST /generate vrátí 400 pro chybějící bankAccount', async () => {
    const { bankAccount: _, ...body } = VALID_BODY;
    const res = await request(buildApp())
        .post('/api/qr/generate')
        .set('Authorization', TOKEN)
        .send(body);
    expect(res.status).toBe(400);
    expect(res.body.error).toContain('účtu');
});

test('POST /generate vrátí 400 pro zápornou částku', async () => {
    const body = {
        ...VALID_BODY,
        recipients: [{ login: 'uzivatel1', purpose: 'Pizza', amount: -1 }],
    };
    const res = await request(buildApp())
        .post('/api/qr/generate')
        .set('Authorization', TOKEN)
        .send(body);
    expect(res.status).toBe(400);
    expect(res.body.error).toContain('částku');
});

test('POST /generate vrátí 400 pro částku s více než 2 desetinnými místy', async () => {
    const body = {
        ...VALID_BODY,
        recipients: [{ login: 'uzivatel1', purpose: 'Pizza', amount: 149.999 }],
    };
    const res = await request(buildApp())
        .post('/api/qr/generate')
        .set('Authorization', TOKEN)
        .send(body);
    expect(res.status).toBe(400);
    expect(res.body.error).toContain('desetinná');
});

test('POST /generate vrátí 400 pro příjemce bez login', async () => {
    const body = {
        ...VALID_BODY,
        recipients: [{ purpose: 'Pizza', amount: 149 }],
    };
    const res = await request(buildApp())
        .post('/api/qr/generate')
        .set('Authorization', TOKEN)
        .send(body);
    expect(res.status).toBe(400);
    expect(res.body.error).toContain('login');
});
