import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { randomUUID } from "node:crypto";
import { getDb } from "@/lib/db";
import { hashPassword, verifyPassword } from "@/lib/auth/password";
import { signToken } from "@/lib/auth/token";
import { requireAuth } from "@/lib/auth/middleware";

const authInput = z.object({
  email: z.string().email(),
  password: z.string().min(6),
});

export const authSignIn = createServerFn({ method: "POST" })
  .inputValidator((d: { email: string; password: string }) => authInput.parse(d))
  .handler(async ({ data }) => {
    const db = getDb();
    const user = db
      .prepare("SELECT id, email, password_hash FROM users WHERE email = ? COLLATE NOCASE")
      .get(data.email) as { id: string; email: string; password_hash: string } | undefined;

    if (!user || !verifyPassword(data.password, user.password_hash)) {
      throw new Error("Неверный email или пароль");
    }

    return { access_token: signToken(user.id) };
  });

export const authSignUp = createServerFn({ method: "POST" })
  .inputValidator((d: { email: string; password: string }) => authInput.parse(d))
  .handler(async ({ data }) => {
    const db = getDb();
    const existing = db
      .prepare("SELECT id FROM users WHERE email = ? COLLATE NOCASE")
      .get(data.email) as { id: string } | undefined;

    if (existing) {
      db.prepare("UPDATE users SET password_hash = ? WHERE id = ?").run(
        hashPassword(data.password),
        existing.id,
      );
      return { access_token: signToken(existing.id) };
    }

    const userId = randomUUID();
    db.prepare("INSERT INTO users (id, email, password_hash) VALUES (?, ?, ?)").run(
      userId,
      data.email,
      hashPassword(data.password),
    );

    const adminCount = db.prepare("SELECT COUNT(*) AS c FROM user_roles WHERE role = 'admin'").get() as {
      c: number;
    };
    if (adminCount.c === 0) {
      db.prepare("INSERT INTO user_roles (id, user_id, role) VALUES (?, ?, 'admin')").run(
        randomUUID(),
        userId,
      );
    }

    return { access_token: signToken(userId) };
  });

export const authMe = createServerFn({ method: "GET" })
  .middleware([requireAuth])
  .handler(async ({ context }) => {
    const db = getDb();
    const user = db
      .prepare("SELECT id, email FROM users WHERE id = ?")
      .get(context.userId) as { id: string; email: string } | undefined;
    if (!user) throw new Error("Пользователь не найден");
    return user;
  });
