import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import bcrypt from "bcryptjs";
import { z } from "zod";

const PatchSchema = z.object({
  username: z.string().min(3).max(64).regex(/^[a-zA-Z0-9_-]+$/).optional(),
  currentPassword: z.string().optional(),
  newPassword: z.string().min(6).max(200).optional(),
  ollamaUrl: z.string().url().optional(),
  defaultModel: z.string().nullable().optional(),
  defaultContext: z.number().int().positive().optional(),
  defaultSystemPrompt: z.string().optional(),
  defaultKeepAlive: z.number().int().min(-1).optional(),
  showThinking: z.boolean().optional(),
  searxngUrl: z.string().url().optional(),
  toolsEnabled: z.boolean().optional(),
  enabledTools: z.string().optional(),
  maxToolIterations: z.number().int().min(1).max(25).optional(),
});

const SELECT = {
  id: true,
  username: true,
  role: true,
  ollamaUrl: true,
  defaultModel: true,
  defaultContext: true,
  defaultSystemPrompt: true,
  defaultKeepAlive: true,
  showThinking: true,
  searxngUrl: true,
  toolsEnabled: true,
  enabledTools: true,
  maxToolIterations: true,
} as const;

export async function GET() {
  const session = await auth();
  if (!session?.user?.id) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  const user = await prisma.user.findUnique({ where: { id: session.user.id }, select: SELECT });
  if (!user) return NextResponse.json({ error: "Not found" }, { status: 404 });
  return NextResponse.json({ user });
}

export async function PATCH(req: NextRequest) {
  const session = await auth();
  if (!session?.user?.id) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const body = await req.json().catch(() => null);
  const parsed = PatchSchema.safeParse(body);
  if (!parsed.success)
    return NextResponse.json({ error: parsed.error.issues[0]?.message ?? "Invalid input" }, { status: 400 });

  const user = await prisma.user.findUnique({ where: { id: session.user.id } });
  if (!user) return NextResponse.json({ error: "Not found" }, { status: 404 });

  const data: Record<string, unknown> = {};
  if (parsed.data.username && parsed.data.username !== user.username) {
    const taken = await prisma.user.findUnique({ where: { username: parsed.data.username } });
    if (taken) return NextResponse.json({ error: "Username taken" }, { status: 409 });
    data.username = parsed.data.username;
  }
  if (parsed.data.newPassword) {
    if (!parsed.data.currentPassword)
      return NextResponse.json({ error: "Current password required" }, { status: 400 });
    const ok = await bcrypt.compare(parsed.data.currentPassword, user.passwordHash);
    if (!ok) return NextResponse.json({ error: "Current password incorrect" }, { status: 400 });
    data.passwordHash = await bcrypt.hash(parsed.data.newPassword, 12);
  }
  if (parsed.data.ollamaUrl !== undefined) data.ollamaUrl = parsed.data.ollamaUrl;
  if (parsed.data.defaultModel !== undefined) data.defaultModel = parsed.data.defaultModel;
  if (parsed.data.defaultContext !== undefined) data.defaultContext = parsed.data.defaultContext;
  if (parsed.data.defaultSystemPrompt !== undefined)
    data.defaultSystemPrompt = parsed.data.defaultSystemPrompt;
  if (parsed.data.defaultKeepAlive !== undefined)
    data.defaultKeepAlive = parsed.data.defaultKeepAlive;
  if (parsed.data.showThinking !== undefined) data.showThinking = parsed.data.showThinking;
  if (parsed.data.searxngUrl !== undefined) data.searxngUrl = parsed.data.searxngUrl;
  if (parsed.data.toolsEnabled !== undefined) data.toolsEnabled = parsed.data.toolsEnabled;
  if (parsed.data.enabledTools !== undefined) data.enabledTools = parsed.data.enabledTools;
  if (parsed.data.maxToolIterations !== undefined)
    data.maxToolIterations = parsed.data.maxToolIterations;

  const updated = await prisma.user.update({
    where: { id: session.user.id },
    data,
    select: SELECT,
  });
  return NextResponse.json({ user: updated });
}
