import { z } from 'zod';
import { prisma } from '@/lib/db';
import { currentUser } from '@/lib/auth';
import { orderCode, payWithCredit } from '@/lib/orders';
import { planById } from '@/lib/plans';
import { TEMPLATES } from '@/lib/templates';
import { VOICES, voiceLang, defaultVoiceFor } from '@/lib/voices';
import { namesOfMahalle } from '@/lib/idari';
import { SALE_IDS, UNIT_TYPES, inPolygon, needsUnit } from '@/lib/sale';
import { startCheckout } from '@/lib/checkout';
import { appUrl, log, rateLimit } from '@/lib/http';
import { PHOTO_MAX, photoKeyOf, tourKeyOf } from '@/lib/photos';

// İstemcinin TKGM'den aldığı parsel poligonu (sunucu IP'si TKGM tarafından engellenebildiği için). Türkiye sınırları içinde olmalı.
const Pt = z.tuple([z.number().min(25).max(45.5), z.number().min(35.5).max(42.5)]);
const Geometry = z.object({ type: z.literal('Polygon'), coordinates: z.array(z.array(Pt).min(4).max(5000)).min(1).max(20) });
const Body = z.object({
  geometry: Geometry.optional(),
  plan: z.string(), template: z.string(), voice: z.string().optional(), batchId: z.string().regex(/^[\w-]{6,40}$/).optional(), deferCheckout: z.boolean().optional(), il: z.string(), ilce: z.string(), mahalle: z.string(), mahalleId: z.number().int(),
  ada: z.string().max(10), parsel: z.string().max(10), areaM2: z.number().optional(), nitelik: z.string().optional(),
  centroidLon: z.number().optional(), centroidLat: z.number().optional(),
  imarDurum: z.string().max(80).optional(), emsal: z.string().max(12).optional(), taks: z.string().max(12).optional(), gabari: z.string().max(12).optional(),
  highlights: z.array(z.string().max(60)).max(4).default([]), headline: z.string().max(80).optional(),
  contactName: z.string().max(60).optional(), contactPhone: z.string().max(30).optional(), aiCloseups: z.boolean().default(false),
  // ne satılıyor
  saleType: z.enum(SALE_IDS).default('arsa'), unitType: z.string().refine((x) => UNIT_TYPES.includes(x)).optional(),
  unitArea: z.number().min(5).max(100000).optional(), rooms: z.string().regex(/^\d{1,2}\+\d{1,2}$/).optional(), floorNo: z.string().max(20).optional(),
  buildYear: z.number().int().min(1850).max(new Date().getFullYear() + 3).optional(), share: z.string().regex(/^\d{1,5}\/\d{1,6}$/).optional(),
  target: Pt.optional(),
  // satılan bölüm (hisse ya da yapı): parselin içinde çizilen çokgen
  targetRing: z.array(Pt).min(3).max(60).optional(),
  // v2: isteğe bağlı ilan fiyatı (TL), karekod linki (yalnızca https), video dili
  price: z.number().int().min(1000).max(5_000_000_000).optional(),
  qrUrl: z.string().max(300).url().refine((x) => x.startsWith('https://'), 'Karekod linki https:// ile başlamalı').optional(),
  lang: z.enum(['tr', 'en', 'ar', 'ru']).default('tr'),
  photoKeys: z.array(z.string().max(80)).max(PHOTO_MAX).default([]),
  tourKey: z.string().max(80).optional(),
}).superRefine((b, ctx) => {
  if (needsUnit(b.saleType) && !b.unitType) ctx.addIssue({ code: 'custom', path: ['unitType'], message: 'Yapı türünü seçin' });
  if (b.saleType === 'hisse' && !b.share) ctx.addIssue({ code: 'custom', path: ['share'], message: 'Hisse oranını yazın (ör. 1/2)' });
  if (b.share) { const [x, y] = b.share.split('/').map(Number); if (!x || !y || x >= y) ctx.addIssue({ code: 'custom', path: ['share'], message: 'Hisse oranı 1/2 gibi, birden küçük olmalı' }); }
  if (b.saleType === 'yapi' && !b.target) ctx.addIssue({ code: 'custom', path: ['target'], message: 'Satılan yapıyı haritada seçin' });
  if (b.target && b.geometry && !inPolygon(b.target, b.geometry.coordinates[0])) ctx.addIssue({ code: 'custom', path: ['target'], message: 'Seçilen yapı parselin içinde olmalı' });
  if (b.targetRing && b.geometry && !b.targetRing.every((p) => inPolygon(p, b.geometry!.coordinates[0]))) ctx.addIssue({ code: 'custom', path: ['targetRing'], message: 'Satılan bölüm parselin içinde çizilmeli' });
});

export async function GET() {
  const u = await currentUser(); if (!u) return Response.json({ error: 'Giriş gerekli' }, { status: 401 });
  if (!u.emailVerifiedAt) return Response.json({ error: 'Sipariş için önce e-posta adresinizi doğrulayın.' }, { status: 403 });
  return Response.json(await prisma.order.findMany({ where: { userId: u.id }, orderBy: { createdAt: 'desc' } }));
}

export async function POST(req: Request) {
  const u = await currentUser(); if (!u) return Response.json({ error: 'Giriş gerekli' }, { status: 401 });
  if (!u.emailVerifiedAt) return Response.json({ error: 'Sipariş için önce e-posta adresinizi doğrulayın.' }, { status: 403 });
  if (!await rateLimit(`ord:${u.id}`, 20, 60_000)) return Response.json({ error: 'Çok fazla istek, biraz bekleyin' }, { status: 429 });
  const parsed = Body.safeParse(await req.json().catch(() => null));
  if (!parsed.success) return Response.json({ error: parsed.error.issues.find((i) => i.code === 'custom')?.message || 'Form eksik veya hatalı', issues: parsed.error.issues }, { status: 400 });
  const b = parsed.data;
  const plan = planById(b.plan); if (!plan) return Response.json({ error: 'Geçersiz paket' }, { status: 400 });
  const vo = b.voice ? VOICES.find((v) => v.id === b.voice) : null;
  if (b.voice && !vo) return Response.json({ error: 'Geçersiz ses' }, { status: 400 });
  if (vo && voiceLang(vo) !== b.lang) return Response.json({ error: 'Seçilen ses bu dilde okumuyor' }, { status: 400 });
  if (!b.voice) b.voice = defaultVoiceFor(b.lang);
  if (!TEMPLATES.some((t) => t.id === b.template)) return Response.json({ error: 'Geçersiz şablon' }, { status: 400 });
  // yalnızca bu kullanıcının yüklediği fotoğraflar (başkasının anahtarı videoya giremez)
  const own = photoKeyOf(u.id);
  if (!b.photoKeys.every((k) => own.test(k))) return Response.json({ error: 'Fotoğraflardan biri geçersiz, yeniden yükleyin' }, { status: 400 });
  b.photoKeys = [...new Set(b.photoKeys)];
  if (b.tourKey && !tourKeyOf(u.id).test(b.tourKey)) return Response.json({ error: '360° fotoğraf geçersiz, yeniden yükleyin' }, { status: 400 });
  const { deferCheckout, target, targetRing, ...rest } = b;
  // satış türüyle ilgisiz alanlar kaydedilmez (ör. arsada oda sayısı)
  const data = { ...rest, ...(needsUnit(b.saleType) ? {} : { unitType: undefined, unitArea: undefined, rooms: undefined, floorNo: undefined, buildYear: undefined }),
    ...(b.saleType === 'hisse' ? {} : { share: undefined }), ...(b.saleType === 'yapi' && target ? { targetLon: target[0], targetLat: target[1] } : {}),
    ...((b.saleType === 'hisse' || b.saleType === 'yapi') && targetRing ? { targetRing } : {}) };
  // TKGM adları ı/İ harflerini kaybediyor ("Kavaklidere"); seslendirme ve kart doğru yazımı kullansın
  Object.assign(data, namesOfMahalle(b.mahalleId) ?? {});
  // logo sipariş anında kopyalanır: kullanıcı sonradan değiştirse de bu video kendi logosuyla üretilir
  const order = await prisma.order.create({ data: { ...data, code: orderCode(), userId: u.id, quality: plan.id === 'ofis' ? 'master' : 'standard', logoKey: u.logoKey, brandColor: u.brandColor } });

  // 1) Kredi varsa direkt kuyruğa
  if (await payWithCredit(u.id, order.id)) return Response.json({ orderId: order.id, redirect: `/panel/siparisler/${order.id}` });

  // Toplu siparişin diğer parselleri: kredi yoksa ödeme sayfası açılmaz, grup ödemesinden sonra kendiliğinden başlar.
  if (deferCheckout) return Response.json({ orderId: order.id, deferred: true });
  // 2) Dodo Payments checkout
  try { return Response.json({ orderId: order.id, redirect: await startCheckout(u, plan, appUrl(req), order.id) }); }
  catch (e) {
    log('error', 'checkout_failed', { orderId: order.id, err: (e as Error).message });
    return Response.json({ orderId: order.id, redirect: `/panel/siparisler/${order.id}`, warning: (e as Error).message }, { status: 200 });
  }
}
