import { NextRequest, NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';
import { sql, transaction } from '@/lib/db/postgres';
import { logApiError, readJsonBody } from '@/lib/api/security';

/** POST /api/codes/redeem — redeem a promo code */
export async function POST(req: NextRequest) {
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();
  if (!user) return NextResponse.json({ error: 'Nicht eingeloggt' }, { status: 401 });

  const body = await readJsonBody<{ code?: unknown }>(req);
  if (!body) return NextResponse.json({ error: 'Ungültige Anfrage' }, { status: 400 });

  const code = 'code' in body ? body.code : null;
  if (typeof code !== 'string' || !code.trim()) {
    return NextResponse.json({ error: 'Kein Code angegeben' }, { status: 400 });
  }

  const normalised = code.toUpperCase().trim();

  try {
    // 1. Find the code
    const { rows: promoRows } = await sql<{
      id: string;
      active: boolean;
      expires_at: string | null;
      uses: number;
      max_uses: number;
      plan: string;
      duration_months: number;
    }>`
      SELECT id, active, expires_at, uses, max_uses, plan, duration_months
      FROM promo_codes
      WHERE code = ${normalised}
      LIMIT 1
    `;

    const promo = promoRows[0];
    if (!promo) return NextResponse.json({ error: 'Ungültiger Code' }, { status: 404 });
    if (!promo.active) return NextResponse.json({ error: 'Dieser Code ist nicht mehr aktiv' }, { status: 410 });
    if (promo.expires_at && new Date(promo.expires_at) < new Date()) {
      return NextResponse.json({ error: 'Dieser Code ist abgelaufen' }, { status: 410 });
    }
    if (promo.uses >= promo.max_uses) {
      return NextResponse.json({ error: 'Dieser Code wurde bereits vollständig eingelöst' }, { status: 410 });
    }

    // 2. Check if user already redeemed
    const { rows: existingRows } = await sql`
      SELECT id FROM promo_code_redemptions
      WHERE code_id = ${promo.id} AND user_id = ${user.id}
      LIMIT 1
    `;
    if (existingRows.length > 0) {
      return NextResponse.json({ error: 'Du hast diesen Code bereits eingelöst' }, { status: 409 });
    }

    // 3. Calculate expiry
    const now = new Date();
    const grantedUntil = new Date(now);
    grantedUntil.setMonth(grantedUntil.getMonth() + promo.duration_months);

    // 4. Apply plan, record redemption, increment usage — all in one transaction
    await transaction(async (client) => {
      await client.query(
        `INSERT INTO user_subscriptions (user_id, plan, status, current_period_start, current_period_end)
         VALUES ($1, $2, 'active', $3, $4)
         ON CONFLICT (user_id) DO UPDATE
         SET plan = EXCLUDED.plan, status = 'active',
             current_period_start = EXCLUDED.current_period_start,
             current_period_end = EXCLUDED.current_period_end`,
        [user.id, promo.plan, now, grantedUntil],
      );

      await client.query(
        `INSERT INTO promo_code_redemptions (code_id, user_id, plan_granted, granted_until)
         VALUES ($1, $2, $3, $4)`,
        [promo.id, user.id, promo.plan, grantedUntil],
      );

      await client.query(
        `UPDATE promo_codes SET uses = uses + 1 WHERE id = $1`,
        [promo.id],
      );
    });

    return NextResponse.json({
      ok: true,
      plan: promo.plan,
      duration_months: promo.duration_months,
      granted_until: grantedUntil.toISOString(),
    });
  } catch (error) {
    logApiError('Codes redeem POST error', error);
    return NextResponse.json({ error: 'Fehler beim Aktivieren des Plans' }, { status: 500 });
  }
}
