const { OAuth2Client } = require('google-auth-library');
const jwt = require('jsonwebtoken');
const User = require('../models/user');
require('dotenv').config();

// Google Client ID should be in env, but for now assuming it handles verification
const googleClient = new OAuth2Client(process.env.GOOGLE_CLIENT_ID);

const generateTokens = (user) => {
  const payload = { id: user.id, email: user.email, nickname: user.nickname };

  const accessToken = jwt.sign(payload, process.env.JWT_SECRET, {
    expiresIn: '1h',
  });

  const refreshToken = jwt.sign({ id: user.id }, process.env.JWT_REFRESH_SECRET, {
    expiresIn: '14d',
  });

  return { accessToken, refreshToken };
};

// Generic Social Login Logic
const socialLogin = async (provider, socialInfo, res) => {
  try {
    const { socialId, email, nickname } = socialInfo;

    // Find or Create User
    const [user, created] = await User.findOrCreate({
      where: { provider, socialId },
      defaults: { email, nickname },
    });

    if (!created) {
      // Update info if needed (e.g., changed nickname on social side) - Optional
      user.email = email || user.email;
      user.nickname = nickname || user.nickname;
    }

    // Generate Tokens
    const { accessToken, refreshToken } = generateTokens(user);

    // Save Refresh Token to DB
    user.refreshToken = refreshToken;
    await user.save();

    console.log(`[Auth] User ${user.id} logged in via ${provider}`);

    return res.status(200).json({
      success: true,
      accessToken,
      refreshToken,
      isNewUser: created, // 신규 가입 여부
      user: {
        id: user.id,
        email: user.email,
        nickname: user.nickname,
      },
    });
  } catch (error) {
    console.error('[Auth Error]', error);
    return res.status(500).json({ success: false, message: 'Internal Server Error' });
  }
};

// Google Login Handler
// Google Login Handler (Check only, or Login if exists)
exports.loginWithGoogle = async (req, res) => {
  const { idToken } = req.body;

  if (!idToken) {
    return res.status(400).json({ success: false, message: 'Missing idToken' });
  }

  try {
    // Verify Google Token
    const ticket = await googleClient.verifyIdToken({
      idToken,
      audience: [
        process.env.GOOGLE_CLIENT_ID,
        process.env.GOOGLE_ANDROID_CLIENT_ID
      ],
    });

    const payload = ticket.getPayload();
    const socialId = payload.sub;

    // Check if user exists
    const user = await User.findOne({ where: { provider: 'google', socialId } });

    if (user) {
      // User exists -> Login
      const { accessToken, refreshToken } = generateTokens(user);
      user.refreshToken = refreshToken;
      await user.save();

      console.log(`[Auth] User ${user.id} logged in via google`);
      return res.status(200).json({
        success: true,
        accessToken,
        refreshToken,
        isNewUser: false,
        user: {
          id: user.id,
          email: user.email,
          nickname: user.nickname,
        },
      });
    } else {
      // User does not exist -> Return isNewUser: true (Do NOT create yet)
      return res.status(200).json({
        success: true,
        isNewUser: true,
        // Optional: Return partial info if needed for UI (e.g. pre-filling name)
        email: payload.email,
        nickname: payload.name,
      });
    }

  } catch (error) {
    console.error('[Google Verify Error]', error);
    return res.status(401).json({
      success: false,
      message: 'Invalid Google Token',
      debug: error.message
    });
  }
};

// Google Register Handler (Create User)
exports.registerWithGoogle = async (req, res) => {
  const { idToken } = req.body;

  if (!idToken) {
    return res.status(400).json({ success: false, message: 'Missing idToken' });
  }

  try {
    // Verify Google Token again
    const ticket = await googleClient.verifyIdToken({
      idToken,
      audience: [
        process.env.GOOGLE_CLIENT_ID,
        process.env.GOOGLE_ANDROID_CLIENT_ID
      ],
    });

    const payload = ticket.getPayload();
    const socialId = payload.sub;
    const email = payload.email;
    const nickname = payload.name;

    // Find or Create User
    const [user, created] = await User.findOrCreate({
      where: { provider: 'google', socialId },
      defaults: { email, nickname },
    });

    // If existing user calls register, just log them in (idempotent)
    const { accessToken, refreshToken } = generateTokens(user);
    user.refreshToken = refreshToken;
    await user.save();

    console.log(`[Auth] User ${user.id} registered/logged in via google`);

    return res.status(200).json({
      success: true,
      accessToken,
      refreshToken,
      isNewUser: created,
      user: {
        id: user.id,
        email: user.email,
        nickname: user.nickname,
      },
    });

  } catch (error) {
    console.error('[Google Register Error]', error);
    return res.status(401).json({
      success: false,
      message: 'Invalid Google Token',
      debug: error.message
    });
  }
};

// Test Login Handler (For verification only)
exports.testLogin = async (req, res) => {
  const { email, nickname } = req.body;

  if (!email || !nickname) {
    return res.status(400).json({ success: false, message: 'Missing email or nickname' });
  }

  // Use 'google' as provider to satisfy DB Enum constraint
  const socialId = `test_${email}`;

  return socialLogin('google', { socialId, email, nickname }, res);
};

// Refresh Token Handler
exports.refreshToken = async (req, res) => {
  const { refreshToken } = req.body;

  if (!refreshToken) {
    return res.status(400).json({ success: false, message: 'Refresh Token required' });
  }

  try {
    const secret = process.env.JWT_REFRESH_SECRET;
    // 1. Verify Refresh Token
    const decoded = jwt.verify(refreshToken, secret);

    // 2. Check DB
    const user = await User.findByPk(decoded.id);
    if (!user || user.refreshToken !== refreshToken) {
      return res.status(403).json({ success: false, message: 'Invalid Refresh Token' });
    }

    // 3. Issue new Access Token
    const payload = { id: user.id, email: user.email, nickname: user.nickname };
    const newAccessToken = jwt.sign(payload, process.env.JWT_SECRET, {
      expiresIn: '1h',
    });

    console.log(`[Auth] Access Token refreshed for User ${user.id}`);

    return res.status(200).json({
      success: true,
      accessToken: newAccessToken,
    });

  } catch (error) {
    console.error('[Refresh Error]', error);
    if (error.name === 'TokenExpiredError') {
      return res.status(403).json({ success: false, message: 'Refresh Token expired' });
    }
    return res.status(403).json({ success: false, message: 'Invalid Refresh Token' });
  }
};

// Get User Info
exports.getMe = async (req, res) => {
  try {
    // req.user is set by middleware
    const user = await User.findByPk(req.user.id);
    if (!user) {
      return res.status(404).json({ success: false, message: 'User not found' });
    }

    return res.status(200).json({
      success: true,
      user: {
        id: user.id,
        email: user.email,
        nickname: user.nickname,
      },
    });
  } catch (error) {
    console.error('[GetMe Error]', error);
    return res.status(500).json({ success: false, message: 'Internal Server Error' });
  }
};

// Withdraw (Delete Account)
exports.withdraw = async (req, res) => {
  try {
    const userId = req.user.id;
    const user = await User.findByPk(userId);

    if (!user) {
      return res.status(404).json({ success: false, message: 'User not found' });
    }

    // Hard Delete
    await user.destroy();

    console.log(`[Auth] User ${userId} withdrew from the service.`);
    return res.status(200).json({ success: true, message: 'Account deleted successfully' });
  } catch (error) {
    console.error('[Withdraw Error]', error);
    return res.status(500).json({ success: false, message: 'Internal Server Error' });
  }
};
