import { router, protectedProcedure, publicProcedure } from "../_core/trpc.ts";
import { z } from "zod";
import {
  generatePasswordResetToken,
  verifyPasswordResetToken,
  resetPasswordWithToken,
  sendPasswordResetEmail,
  createSupportTicket,
  getSupportTicket,
  getUserSupportTickets,
  updateSupportTicketStatus,
} from "../services/accountRecovery.ts";
import { hashPassword } from "../services/passwordAuth.ts";

export const accountRecoveryRouter = router({
  // Request password reset
  requestPasswordReset: publicProcedure
    .input(
      z.object({
        email: z.string().email(),
        origin: z.string().url(),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const token = await generatePasswordResetToken(input.email);
        if (!token) {
          // Don't reveal if email exists
          return {
            success: true,
            message: "If an account exists with this email, a password reset link has been sent.",
          };
        }

        await sendPasswordResetEmail(input.email, token, input.origin);

        return {
          success: true,
          message: "Password reset email sent successfully",
        };
      } catch (error) {
        console.error("[Account Recovery] Password reset request failed:", error);
        throw new Error("Failed to process password reset request");
      }
    }),

  // Verify password reset token
  verifyResetToken: publicProcedure
    .input(z.object({ token: z.string() }))
    .query(async ({ input }) => {
      const userId = await verifyPasswordResetToken(input.token);
      return {
        isValid: !!userId,
      };
    }),

  // Reset password with token
  resetPassword: publicProcedure
    .input(
      z.object({
        token: z.string(),
        newPassword: z.string().min(8),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const passwordHash = await hashPassword(input.newPassword);
        const success = await resetPasswordWithToken(input.token, passwordHash);

        if (!success) {
          throw new Error("Invalid or expired reset token");
        }

        return {
          success: true,
          message: "Password reset successfully",
        };
      } catch (error) {
        console.error("[Account Recovery] Password reset failed:", error);
        throw new Error("Failed to reset password");
      }
    }),

  // Create support ticket
  createSupportTicket: publicProcedure
    .input(
      z.object({
        email: z.string().email(),
        subject: z.string().min(5).max(200),
        message: z.string().min(10).max(5000),
        category: z.enum(["account", "payment", "technical", "other"]),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const ticket = await createSupportTicket({
          email: input.email,
          subject: input.subject,
          message: input.message,
          category: input.category,
        });

        return {
          success: true,
          ticketId: ticket.id,
          message: "Support ticket created successfully",
        };
      } catch (error) {
        console.error("[Support] Failed to create ticket:", error);
        throw new Error("Failed to create support ticket");
      }
    }),

  // Get support ticket (public - requires ticket ID)
  getSupportTicket: publicProcedure
    .input(z.object({ ticketId: z.string() }))
    .query(async ({ input }) => {
      try {
        const ticket = await getSupportTicket(input.ticketId);
        if (!ticket) {
          throw new Error("Ticket not found");
        }
        return ticket;
      } catch (error) {
        console.error("[Support] Failed to get ticket:", error);
        throw new Error("Failed to retrieve support ticket");
      }
    }),

  // Get user's support tickets (protected)
  getUserTickets: protectedProcedure.query(async ({ ctx }) => {
    try {
      if (!ctx.user?.id) {
        throw new Error("User not authenticated");
      }
      const tickets = await getUserSupportTickets(ctx.user.id);
      return tickets;
    } catch (error) {
      console.error("[Support] Failed to get user tickets:", error);
      throw new Error("Failed to retrieve support tickets");
    }
  }),

  // Update ticket status (protected - admin only)
  updateTicketStatus: protectedProcedure
    .input(
      z.object({
        ticketId: z.string(),
        status: z.enum(["open", "in_progress", "resolved"]),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        // Check if user is admin (simplified - implement proper role check)
        if (ctx.user?.role !== "admin") {
          throw new Error("Only admins can update ticket status");
        }

        const success = await updateSupportTicketStatus(input.ticketId, input.status);
        if (!success) {
          throw new Error("Ticket not found");
        }

        return {
          success: true,
          message: "Ticket status updated successfully",
        };
      } catch (error) {
        console.error("[Support] Failed to update ticket:", error);
        throw new Error("Failed to update support ticket");
      }
    }),
});
