import { Request, Response } from "express";
import jwt from "jsonwebtoken";
import User from "../models/user";
import { stripe } from "../utils/stripeInstance";
import NotificationSettings from "../models/notificationSettings";

// Signs the app's own session JWT, same payload shape login.ts uses, so
// requireAuth (which verifies against JWT_SECRET) accepts it. The `token`
// field in the request/DB is the raw provider (Google/Apple) token — that's
// never valid here, since it's signed by the provider, not by us.
function signAppToken(userWithoutPassword: any): Promise<string> {
  return new Promise((resolve, reject) => {
    jwt.sign(
      { user: userWithoutPassword },
      process.env.JWT_SECRET!,
      {},
      (err, token) => (err || !token ? reject(err) : resolve(token)),
    );
  });
}

class SocialLoginController {
  static async Execute(req: Request, res: Response) {
    const { email, name, loginProvider, role, token, FCMToken, appleUserId } =
      req.body;
    console.log(req.body);

    if (!loginProvider || !role || !token) {
      return res.status(400).send({ message: "Invalid request" });
    }

    if (!process.env.JWT_SECRET) {
      return res.status(500).send({ message: "Failed to generate token" });
    }

    try {
      const normalizedEmail = email ? email.trim().toLowerCase() : null;
      let user;

      if (normalizedEmail) {
        user = await User.findOne({ email: normalizedEmail });
      } else if (loginProvider === "Apple") {
        user = await User.findOne({ appleUserId });
      }

      if (user) {
        user.token = token;
        if (FCMToken) user.FCMToken = FCMToken;
        user.lastLogin = new Date();
        await user.save();

        const userWithoutPassword = user.toJSON();
        delete userWithoutPassword.password;
        userWithoutPassword.token = await signAppToken(userWithoutPassword);

        return res.status(200).send({
          message: "User updated successfully",
          user: userWithoutPassword,
        });
      } else {
        if (!normalizedEmail) {
          return res.status(400).send({
            message:
              "Apple did not return an email. Cannot create new user without an email.",
          });
        }

        // Create Stripe customer for new user
        const customer = await stripe.customers.create({
          name: name?.trim(),
          email: normalizedEmail,
        });

        // Create new user
        const newUser = new User({
          name: name?.trim(),
          email: normalizedEmail,
          loginProvider,
          role,
          token,
          FCMToken,
          emailVerified: true,
          stripeCustomerId: customer.id,
          appleUserId,
        });

        await newUser.save();

        // Create default notification settings
        const notificationSettings = new NotificationSettings({
          user: newUser._id,
        });

        await notificationSettings.save();

        const userWithoutPassword = newUser.toJSON();
        delete userWithoutPassword.password;
        userWithoutPassword.token = await signAppToken(userWithoutPassword);

        return res.status(200).send({
          message: "User created successfully",
          user: userWithoutPassword,
        });
      }
    } catch (err) {
      console.error("SocialLoginController error:", err);
      return res.status(500).send({
        message: "Internal server error",
        error: err,
      });
    }
  }
}

module.exports = SocialLoginController;
