import { NextResponse } from 'next/server';
import {
  GuildPremiumAssignSchema,
  PremiumTierConfigPatchSchema,
  PremiumTierSchema,
  UserPremiumAssignSchema
} from '@nexumi/shared';
import { toApiErrorResponse } from '@/lib/auth';
import { writeOwnerAudit } from '@/lib/owner-audit';
import { requireOwner } from '@/lib/owner-auth';
import { ensurePremiumTierConfigs } from '@/lib/premium';
import { prisma } from '@/lib/prisma';

export async function GET() {
  try {
    await requireOwner('VIEWER');
    const [tiers, guilds, users] = await Promise.all([
      ensurePremiumTierConfigs(prisma),
      prisma.guildPremiumAssignment.findMany({ orderBy: { updatedAt: 'desc' } }),
      prisma.userPremiumAssignment.findMany({ orderBy: { updatedAt: 'desc' } })
    ]);
    return NextResponse.json({
      tiers,
      guilds: guilds.map((row) => ({
        ...row,
        expiresAt: row.expiresAt?.toISOString() ?? null,
        createdAt: row.createdAt.toISOString(),
        updatedAt: row.updatedAt.toISOString()
      })),
      users: users.map((row) => ({
        ...row,
        expiresAt: row.expiresAt?.toISOString() ?? null,
        createdAt: row.createdAt.toISOString(),
        updatedAt: row.updatedAt.toISOString()
      }))
    });
  } catch (error) {
    return toApiErrorResponse(error);
  }
}

export async function PATCH(request: Request) {
  try {
    const session = await requireOwner('ADMIN');
    const body = await request.json();
    const tier = PremiumTierSchema.parse(body.tier);
    const patch = PremiumTierConfigPatchSchema.parse(body);
    await ensurePremiumTierConfigs(prisma);
    const before = await prisma.premiumTierConfig.findUniqueOrThrow({ where: { tier } });
    const after = await prisma.premiumTierConfig.update({
      where: { tier },
      data: {
        ...(patch.maxTags !== undefined ? { maxTags: patch.maxTags } : {}),
        ...(patch.maxFeeds !== undefined ? { maxFeeds: patch.maxFeeds } : {}),
        ...(patch.maxBackups !== undefined ? { maxBackups: patch.maxBackups } : {}),
        ...(patch.features !== undefined ? { features: patch.features } : {})
      }
    });
    await writeOwnerAudit(prisma, {
      actorUserId: session.user.id,
      action: 'premium.tier.update',
      targetType: 'PremiumTierConfig',
      targetId: tier,
      before,
      after
    });
    return NextResponse.json(after);
  } catch (error) {
    return toApiErrorResponse(error);
  }
}

export async function PUT(request: Request) {
  try {
    const session = await requireOwner('ADMIN');
    const body = await request.json();
    const kind = body.kind === 'user' ? 'user' : 'guild';

    if (kind === 'user') {
      const input = UserPremiumAssignSchema.parse(body);
      const before = await prisma.userPremiumAssignment.findUnique({ where: { userId: input.userId } });
      const after = await prisma.userPremiumAssignment.upsert({
        where: { userId: input.userId },
        create: {
          userId: input.userId,
          tier: input.tier,
          note: input.note ?? null,
          assignedById: session.user.id,
          expiresAt: input.expiresAt ? new Date(input.expiresAt) : null
        },
        update: {
          tier: input.tier,
          note: input.note ?? null,
          assignedById: session.user.id,
          expiresAt: input.expiresAt ? new Date(input.expiresAt) : null
        }
      });
      await writeOwnerAudit(prisma, {
        actorUserId: session.user.id,
        action: before ? 'premium.user.update' : 'premium.user.assign',
        targetType: 'UserPremiumAssignment',
        targetId: after.userId,
        before,
        after
      });
      return NextResponse.json(after);
    }

    const input = GuildPremiumAssignSchema.parse(body);
    await prisma.guild.upsert({ where: { id: input.guildId }, update: {}, create: { id: input.guildId } });
    const before = await prisma.guildPremiumAssignment.findUnique({ where: { guildId: input.guildId } });
    const after = await prisma.guildPremiumAssignment.upsert({
      where: { guildId: input.guildId },
      create: {
        guildId: input.guildId,
        tier: input.tier,
        note: input.note ?? null,
        assignedById: session.user.id,
        expiresAt: input.expiresAt ? new Date(input.expiresAt) : null
      },
      update: {
        tier: input.tier,
        note: input.note ?? null,
        assignedById: session.user.id,
        expiresAt: input.expiresAt ? new Date(input.expiresAt) : null
      }
    });
    await writeOwnerAudit(prisma, {
      actorUserId: session.user.id,
      action: before ? 'premium.guild.update' : 'premium.guild.assign',
      targetType: 'GuildPremiumAssignment',
      targetId: after.guildId,
      before,
      after
    });
    return NextResponse.json(after);
  } catch (error) {
    return toApiErrorResponse(error);
  }
}

export async function DELETE(request: Request) {
  try {
    const session = await requireOwner('ADMIN');
    const url = new URL(request.url);
    const guildId = url.searchParams.get('guildId');
    const userId = url.searchParams.get('userId');

    if (guildId) {
      const before = await prisma.guildPremiumAssignment.findUnique({ where: { guildId } });
      if (!before) {
        return NextResponse.json({ error: 'Not found' }, { status: 404 });
      }
      await prisma.guildPremiumAssignment.delete({ where: { guildId } });
      await writeOwnerAudit(prisma, {
        actorUserId: session.user.id,
        action: 'premium.guild.remove',
        targetType: 'GuildPremiumAssignment',
        targetId: guildId,
        before
      });
      return NextResponse.json({ ok: true });
    }

    if (userId) {
      const before = await prisma.userPremiumAssignment.findUnique({ where: { userId } });
      if (!before) {
        return NextResponse.json({ error: 'Not found' }, { status: 404 });
      }
      await prisma.userPremiumAssignment.delete({ where: { userId } });
      await writeOwnerAudit(prisma, {
        actorUserId: session.user.id,
        action: 'premium.user.remove',
        targetType: 'UserPremiumAssignment',
        targetId: userId,
        before
      });
      return NextResponse.json({ ok: true });
    }

    return NextResponse.json({ error: 'guildId or userId required' }, { status: 400 });
  } catch (error) {
    return toApiErrorResponse(error);
  }
}
