import { COOKIE_NAME } from "@shared/const";
import { getSessionCookieOptions } from "./_core/cookies";
import { systemRouter } from "./_core/systemRouter";
import { publicProcedure, router, protectedProcedure } from "./_core/trpc";
import { getTeamMembers, getTeamMemberById, createTeamMember, updateTeamMember, deleteTeamMember } from "./db";
import { registerUser, authenticateUser, validatePasswordStrength } from "./auth";
import { z } from "zod";
import { TRPCError } from "@trpc/server";

export const appRouter = router({
  system: systemRouter,
  auth: router({
    me: publicProcedure.query(opts => opts.ctx.user),
    
    logout: publicProcedure.mutation(({ ctx }) => {
      const cookieOptions = getSessionCookieOptions(ctx.req);
      ctx.res.clearCookie(COOKIE_NAME, { ...cookieOptions, maxAge: -1 });
      return {
        success: true,
      } as const;
    }),

    /**
     * Register a new admin user with email and password
     */
    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 {
          const passwordValidation = validatePasswordStrength(input.password);
          if (!passwordValidation.valid) {
            throw new TRPCError({
              code: "BAD_REQUEST",
              message: passwordValidation.errors.join("; "),
            });
          }

          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
     */
    login: publicProcedure
      .input(
        z.object({
          email: z.string().email("Invalid email format"),
          password: z.string().min(1, "Password required"),
        })
      )
      .mutation(async ({ input, ctx }) => {
        try {
          const user = await authenticateUser(input.email, input.password);

          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,
        };
      }),
  }),

  team: router({
    list: publicProcedure.query(() => getTeamMembers()),

    getById: publicProcedure
      .input(z.object({ id: z.number() }))
      .query(({ input }) => getTeamMemberById(input.id)),

    create: protectedProcedure
      .input(z.object({
        name: z.string().min(1),
        role: z.string().min(1),
        department: z.string().optional(),
        bio: z.string().optional(),
        imageUrl: z.string().optional(),
        email: z.string().email().optional(),
        phone: z.string().optional(),
        isExecutive: z.number().optional(),
        displayOrder: z.number().optional(),
      }))
      .mutation(async ({ ctx, input }) => {
        if (ctx.user?.role !== 'admin') {
          throw new TRPCError({ code: 'FORBIDDEN', message: 'Only admins can create team members' });
        }
        return createTeamMember(input);
      }),

    update: protectedProcedure
      .input(z.object({
        id: z.number(),
        data: z.object({
          name: z.string().optional(),
          role: z.string().optional(),
          department: z.string().optional(),
          bio: z.string().optional(),
          imageUrl: z.string().optional(),
          email: z.string().email().optional(),
          phone: z.string().optional(),
          isExecutive: z.number().optional(),
          displayOrder: z.number().optional(),
        }),
      }))
      .mutation(async ({ ctx, input }) => {
        if (ctx.user?.role !== 'admin') {
          throw new TRPCError({ code: 'FORBIDDEN', message: 'Only admins can update team members' });
        }
        return updateTeamMember(input.id, input.data);
      }),

    delete: protectedProcedure
      .input(z.object({ id: z.number() }))
      .mutation(async ({ ctx, input }) => {
        if (ctx.user?.role !== 'admin') {
          throw new TRPCError({ code: 'FORBIDDEN', message: 'Only admins can delete team members' });
        }
        return deleteTeamMember(input.id);
      }),
  }),
});

export type AppRouter = typeof appRouter;
