import { describe, it, expect, beforeEach, vi } from 'vitest';
import type { User } from '@prisma/client';
import { prisma } from '@/lib/db';
import { resetDb, mkUser } from './helpers';

const me = vi.hoisted(() => ({ user: null as User | null }));
vi.mock('@/lib/auth', () => ({ currentUser: async () => me.user }));
const { POST } = await import('@/app/api/orders/route');

beforeEach(async () => { await resetDb(); me.user = null; });

const order = { plan: 'tek', template: 'prestij', il: 'Muğla', ilce: 'Ula', mahalle: 'Gökova', mahalleId: 137536, ada: '101', parsel: '5' };
const req = () => new Request('http://x/api/orders', { method: 'POST', body: JSON.stringify(order), headers: { 'content-type': 'application/json' } });

describe('POST /api/orders', () => {
  it('e-postası doğrulanmamış kullanıcı sipariş veremez', async () => {
    me.user = await prisma.user.update({ where: { id: (await mkUser(1)).id }, data: { emailVerifiedAt: null } });
    const r = await POST(req());
    expect(r.status).toBe(403);
    expect(await prisma.order.count()).toBe(0);
    expect((await prisma.user.findUnique({ where: { id: me.user.id } }))!.credits).toBe(1);
  });
  it('doğrulanmış kullanıcı kredisiyle sipariş verir', async () => {
    me.user = await mkUser(1);
    const r = await POST(req());
    expect(r.status).toBe(200);
    const { orderId } = await r.json();
    expect((await prisma.order.findUnique({ where: { id: orderId } }))!.status).toBe('QUEUED');
  });
  it("TKGM'den bozuk gelen adları mahalle kimliğine göre düzeltip kaydeder", async () => {
    me.user = await mkUser(1);
    const body = { ...order, il: 'Adana', ilce: 'Aladağ', mahalle: 'Akpinar', mahalleId: 45478 };
    const r = await POST(new Request('http://x/api/orders', { method: 'POST', body: JSON.stringify(body), headers: { 'content-type': 'application/json' } }));
    const { orderId } = await r.json();
    expect((await prisma.order.findUnique({ where: { id: orderId } }))!.mahalle).toBe('Akpınar');
  });
});

describe('POST /api/orders · ne satılıyor', () => {
  const geometry = { type: 'Polygon', coordinates: [[[28.36734, 37.05169], [28.36719, 37.05174], [28.3671, 37.05151], [28.36703, 37.05133], [28.36718, 37.05129], [28.36726, 37.05148], [28.36734, 37.05169]]] };
  const post = (extra: Record<string, unknown>) => POST(new Request('http://x/api/orders', { method: 'POST', body: JSON.stringify({ ...order, geometry, ...extra }), headers: { 'content-type': 'application/json' } }));
  it('parseldeki yapılardan biri: seçilen yapı parselin içinde olmalı', async () => {
    me.user = await mkUser(3);
    const r1 = await post({ saleType: 'yapi', unitType: 'Müstakil ev' });
    expect(r1.status).toBe(400); expect((await r1.json()).error).toMatch(/haritada/);
    const r2 = await post({ saleType: 'yapi', unitType: 'Müstakil ev', target: [28.40, 37.10] });
    expect(r2.status).toBe(400); expect((await r2.json()).error).toMatch(/parselin içinde/);
    const r3 = await post({ saleType: 'yapi', unitType: 'Müstakil ev', unitArea: 95, rooms: '2+1', target: [28.36718, 37.05150] });
    expect(r3.status).toBe(200);
    const o = await prisma.order.findUnique({ where: { id: (await r3.json()).orderId } });
    expect(o).toMatchObject({ saleType: 'yapi', unitType: 'Müstakil ev', unitArea: 95, rooms: '2+1', targetLon: 28.36718, targetLat: 37.0515 });
  });
  it('yapı türü gereken seçenekte yapı türü zorunlu', async () => {
    me.user = await mkUser(1);
    expect((await post({ saleType: 'tamami' })).status).toBe(400);
  });
  it('hisse oranı birden küçük olmalı', async () => {
    me.user = await mkUser(1);
    expect((await post({ saleType: 'hisse', share: '3/2' })).status).toBe(400);
    const ok = await post({ saleType: 'hisse', share: '1/2', rooms: '3+1' });
    const o = await prisma.order.findUnique({ where: { id: (await ok.json()).orderId } });
    expect(o).toMatchObject({ saleType: 'hisse', share: '1/2', rooms: null }); // hissede oda sayısı kaydedilmez
  });
  it('varsayılan boş arsa; ilgisiz alanlar kaydedilmez', async () => {
    me.user = await mkUser(1);
    const r = await post({ rooms: '3+1', unitArea: 120 });
    const o = await prisma.order.findUnique({ where: { id: (await r.json()).orderId } });
    expect(o).toMatchObject({ saleType: 'arsa', rooms: null, unitArea: null });
  });
});

describe('POST /api/orders · v2 (dil, fiyat, karekod)', () => {
  const post = (extra: Record<string, unknown>) => POST(new Request('http://x/api/orders', { method: 'POST', body: JSON.stringify({ ...order, ...extra }), headers: { 'content-type': 'application/json' } }));
  it('İngilizce sipariş İngilizce sesle kaydedilir; ses verilmezse dilin varsayılanı atanır', async () => {
    me.user = await mkUser(3);
    const r = await post({ lang: 'en', price: 3750000, qrUrl: 'https://wa.me/905320000000' });
    expect(r.status).toBe(200);
    const o = await prisma.order.findUnique({ where: { id: (await r.json()).orderId } });
    expect(o).toMatchObject({ lang: 'en', voice: 'daniel', price: 3750000, qrUrl: 'https://wa.me/905320000000' });
  });
  it('dil ile ses uyuşmazsa reddedilir', async () => {
    me.user = await mkUser(1);
    const r = await post({ lang: 'en', voice: 'fatih' });
    expect(r.status).toBe(400); expect((await r.json()).error).toMatch(/bu dilde/);
  });
  it('karekod linki yalnızca https; dil verilmezse Türkçe', async () => {
    me.user = await mkUser(2);
    expect((await post({ qrUrl: 'http://ornek.com' })).status).toBe(400);
    const r = await post({});
    const o = await prisma.order.findUnique({ where: { id: (await r.json()).orderId } });
    expect(o).toMatchObject({ lang: 'tr', price: null, qrUrl: null });
  });
});
