import { describe, it, expect, beforeEach, beforeAll } from 'vitest';
import { prisma } from '@/lib/db';
import { payWithCredit, enqueueOrder } from '@/lib/orders';
import { signAgent } from '@/lib/agentAuth';
import { GET as listPending } from '@/app/api/agent/orders/route';
import { POST as claim } from '@/app/api/agent/orders/[id]/claim/route';
import { POST as deliver } from '@/app/api/agent/orders/[id]/deliver/route';
import { resetDb, mkUser, mkOrder } from './helpers';

beforeAll(() => { process.env.ORDER_WEBHOOK_SECRET = 's3cret'; });
beforeEach(resetDb);

const agentReq = (url: string, method = 'GET', body = '') => {
  const u = new URL(url); const { ts, sig } = signAgent(method === 'GET' ? u.pathname + u.search : body);
  return new Request(url, { method, body: method === 'GET' ? undefined : body, headers: { 'x-parsel-timestamp': ts, 'x-parsel-signature': sig, 'content-type': 'application/json' } });
};
const ctx = (id: string) => ({ params: Promise.resolve({ id }) });

describe('sipariş akışı', () => {
  it('kredi yoksa ödeme yapılmaz', async () => {
    const u = await mkUser(0); const o = await mkOrder(u.id);
    expect(await payWithCredit(u.id, o.id)).toBe(false);
    expect((await prisma.order.findUnique({ where: { id: o.id } }))!.status).toBe('PENDING_PAYMENT');
  });
  it('kredi ile ödeme: kredi düşer, iş oluşur', async () => {
    const u = await mkUser(2); const o = await mkOrder(u.id);
    expect(await payWithCredit(u.id, o.id)).toBe(true);
    expect((await prisma.user.findUnique({ where: { id: u.id } }))!.credits).toBe(1);
    expect(await prisma.job.count({ where: { orderId: o.id, status: 'queued' } })).toBe(1);
  });
  it('zaten ödenmiş siparişe kredi harcanmaz', async () => {
    const u = await mkUser(2); const o = await mkOrder(u.id);
    expect(await payWithCredit(u.id, o.id)).toBe(true);
    expect(await payWithCredit(u.id, o.id)).toBe(false);
    expect((await prisma.user.findUnique({ where: { id: u.id } }))!.credits).toBe(1);
    expect(await prisma.job.count({ where: { orderId: o.id } })).toBe(1);
  });
  it('kredi yetmezse sipariş ödenmiş işaretlenmez', async () => {
    const u = await mkUser(0); const o = await mkOrder(u.id);
    await payWithCredit(u.id, o.id);
    expect((await prisma.order.findUnique({ where: { id: o.id } }))!.status).toBe('PENDING_PAYMENT');
    expect(await prisma.job.count({ where: { orderId: o.id } })).toBe(0);
  });
  it('enqueueOrder idempotenttir', async () => {
    const u = await mkUser(); const o = await mkOrder(u.id, { status: 'PAID' });
    await enqueueOrder(o.id); await enqueueOrder(o.id);
    expect(await prisma.job.count({ where: { orderId: o.id } })).toBe(1);
  });
  it('harici ajan: listele → sahiplen → teslim et', async () => {
    const u = await mkUser(1); const o = await mkOrder(u.id); await payWithCredit(u.id, o.id);
    const unsigned = await listPending(new Request('http://x/api/agent/orders'));
    expect(unsigned.status).toBe(401);
    const list = await (await listPending(agentReq('http://x/api/agent/orders'))).json();
    expect(list.map((x: { id: string }) => x.id)).toContain(o.id);
    const c1 = await claim(agentReq(`http://x/api/agent/orders/${o.id}/claim`, 'POST', '{"agent":"grok"}'), ctx(o.id));
    expect(c1.status).toBe(200);
    const c2 = await claim(agentReq(`http://x/api/agent/orders/${o.id}/claim`, 'POST', '{"agent":"other"}'), ctx(o.id));
    expect(c2.status).toBe(409);
    const d = await deliver(agentReq(`http://x/api/agent/orders/${o.id}/deliver`, 'POST', JSON.stringify({ videoUrl: 'https://cdn.example.com/v.mp4', durationSec: 30 })), ctx(o.id));
    expect(d.status).toBe(200);
    const o2 = await prisma.order.findUnique({ where: { id: o.id } });
    expect(o2!.status).toBe('DELIVERED');
    expect(o2!.videoUrl).toBe('https://cdn.example.com/v.mp4');
  });
});
