import { router, publicProcedure, protectedProcedure } from "../_core/trpc.ts";
import { z } from "zod";
import { SocialOAuthService } from "../services/socialOAuth.ts";

export const authSocialOAuthRouter = router({
  /**
   * Get OAuth authorization URL
   */
  getAuthUrl: publicProcedure
    .input(
      z.object({
        provider: z.enum(["google", "github", "apple"]),
        state: z.string().optional(),
      })
    )
    .query(({ input }) => {
      try {
        const authUrl = SocialOAuthService.getAuthorizationUrl(input.provider, input.state);

        return {
          success: true,
          authUrl,
          provider: input.provider,
        };
      } catch (error) {
        console.error("[OAuth] Error getting auth URL:", error);
        throw new Error(`Failed to get ${input.provider} authorization URL`);
      }
    }),

  /**
   * Exchange authorization code for token
   */
  exchangeCode: publicProcedure
    .input(
      z.object({
        provider: z.enum(["google", "github", "apple"]),
        code: z.string(),
        state: z.string(),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const token = await SocialOAuthService.exchangeCodeForToken(
          input.provider,
          input.code,
          input.state
        );

        return {
          success: true,
          token,
          provider: input.provider,
        };
      } catch (error) {
        console.error("[OAuth] Error exchanging code:", error);
        throw new Error(`Failed to exchange ${input.provider} authorization code`);
      }
    }),

  /**
   * Get user info from OAuth provider
   */
  getUserInfo: publicProcedure
    .input(
      z.object({
        provider: z.enum(["google", "github", "apple"]),
        accessToken: z.string(),
      })
    )
    .query(async ({ input }) => {
      try {
        const userInfo = await SocialOAuthService.getUserInfo(input.provider, input.accessToken);

        return {
          success: true,
          user: userInfo,
          provider: input.provider,
        };
      } catch (error) {
        console.error("[OAuth] Error getting user info:", error);
        throw new Error(`Failed to get ${input.provider} user information`);
      }
    }),

  /**
   * Link OAuth account to existing user
   */
  linkAccount: protectedProcedure
    .input(
      z.object({
        provider: z.enum(["google", "github", "apple"]),
        oauthId: z.string(),
        accessToken: z.string(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      try {
        const result = await SocialOAuthService.linkOAuthAccount(
          ctx.user.id,
          input.provider,
          input.oauthId,
          input.accessToken
        );

        return {
          success: true,
          message: `${input.provider} account linked successfully`,
          ...result,
        };
      } catch (error) {
        console.error("[OAuth] Error linking account:", error);
        throw new Error(`Failed to link ${input.provider} account`);
      }
    }),

  /**
   * Find or create user from OAuth
   */
  findOrCreateUser: publicProcedure
    .input(
      z.object({
        provider: z.enum(["google", "github", "apple"]),
        oauthId: z.string(),
        email: z.string().email(),
        name: z.string(),
        picture: z.string().optional(),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const user = await SocialOAuthService.findOrCreateUser(
          input.provider,
          input.oauthId,
          input.email,
          input.name,
          input.picture
        );

        return {
          success: true,
          user: {
            id: user.id,
            email: user.email,
            name: user.name,
          },
          provider: input.provider,
          isNewUser: !("createdAt" in user),
        };
      } catch (error) {
        console.error("[OAuth] Error finding/creating user:", error);
        throw new Error(`Failed to process ${input.provider} authentication`);
      }
    }),

  /**
   * Revoke OAuth access
   */
  revokeAccess: protectedProcedure
    .input(
      z.object({
        provider: z.enum(["google", "github", "apple"]),
        accessToken: z.string(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      try {
        const result = await SocialOAuthService.revokeAccess(input.provider, input.accessToken);

        return {
          success: true,
          message: `${input.provider} access revoked`,
          ...result,
        };
      } catch (error) {
        console.error("[OAuth] Error revoking access:", error);
        throw new Error(`Failed to revoke ${input.provider} access`);
      }
    }),

  /**
   * Get list of connected OAuth providers for user
   */
  getConnectedProviders: protectedProcedure.query(async ({ ctx }) => {
    try {
      // In production, fetch from database
      const providers = ["google", "github", "apple"];
      const connected = providers.filter((p) => Math.random() > 0.5);

      return {
        success: true,
        connected: connected as Array<"google" | "github" | "apple">,
        available: providers as Array<"google" | "github" | "apple">,
      };
    } catch (error) {
      console.error("[OAuth] Error getting connected providers:", error);
      throw new Error("Failed to get connected providers");
    }
  }),
});
