import { router, publicProcedure } from "./_core/trpc";
import { z } from "zod";
import { TRPCError } from "@trpc/server";
import { registerUser, authenticateUser, validatePasswordStrength } from "./auth";
import { getUserByEmail } from "./db";

export const authRouter = router({
  /**
   * Register a new admin user
   * Password must meet security requirements
   */
  register: publicProcedure
    .input(
      z.object({
        email: z.string().email("Invalid email format"),
        password: z.string().min(8, "Password must be at least 8 characters"),
        name: z.string().optional(),
      })
    )
    .mutation(async ({ input }) => {
      try {
        // Validate password strength
        const passwordValidation = validatePasswordStrength(input.password);
        if (!passwordValidation.valid) {
          throw new TRPCError({
            code: "BAD_REQUEST",
            message: passwordValidation.errors.join("; "),
          });
        }

        // Check if user already exists
        const existingUser = await getUserByEmail(input.email);
        if (existingUser) {
          throw new TRPCError({
            code: "CONFLICT",
            message: "Email already registered",
          });
        }

        // Register user
        await registerUser(input.email, input.password, input.name);

        return {
          success: true,
          message: "Registration successful. Please log in.",
        };
      } catch (error) {
        if (error instanceof TRPCError) throw error;
        throw new TRPCError({
          code: "INTERNAL_SERVER_ERROR",
          message: error instanceof Error ? error.message : "Registration failed",
        });
      }
    }),

  /**
   * Login with email and password
   * Returns user data and session token
   */
  login: publicProcedure
    .input(
      z.object({
        email: z.string().email("Invalid email format"),
        password: z.string().min(1, "Password required"),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        // Authenticate user
        const user = await authenticateUser(input.email, input.password);

        // Set session cookie
        const sessionToken = Buffer.from(
          JSON.stringify({
            userId: user.id,
            email: user.email,
            role: user.role,
          })
        ).toString("base64");

        ctx.res.setHeader("Set-Cookie", `session=${sessionToken}; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=86400`);

        return {
          success: true,
          user: {
            id: user.id,
            email: user.email,
            name: user.name,
            role: user.role,
          },
        };
      } catch (error) {
        throw new TRPCError({
          code: "UNAUTHORIZED",
          message: error instanceof Error ? error.message : "Login failed",
        });
      }
    }),

  /**
   * Get password strength requirements
   */
  getPasswordRequirements: publicProcedure.query(() => ({
    minLength: 8,
    requirements: [
      "At least 8 characters",
      "At least one uppercase letter (A-Z)",
      "At least one lowercase letter (a-z)",
      "At least one number (0-9)",
      "At least one special character (!@#$%^&*)",
    ],
  })),

  /**
   * Validate password strength
   */
  validatePassword: publicProcedure
    .input(z.object({ password: z.string() }))
    .query(({ input }) => {
      const validation = validatePasswordStrength(input.password);
      return {
        valid: validation.valid,
        errors: validation.errors,
      };
    }),
});
