const router = require('express').Router();
const fetch  = require('node-fetch');
const db     = require('../lib/db');

const CLIENT_ID     = process.env.GOOGLE_CLIENT_ID;
const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
const REDIRECT      = process.env.GOOGLE_REDIRECT || 'https://vianexu.com/google/callback';
const SCOPES        = [
  'https://www.googleapis.com/auth/business.manage',
  'openid', 'email', 'profile'
].join(' ');

const GBP = 'https://mybusinessaccountmanagement.googleapis.com/v1';
const GBI = 'https://mybusinessbusinessinformation.googleapis.com/v1';
const GBR = 'https://mybusiness.googleapis.com/v4'; // reviews

// ── helpers ───────────────────────────────────────────────────────────────────
async function refreshAccessToken(user) {
  const r = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_id: CLIENT_ID, client_secret: CLIENT_SECRET,
      grant_type: 'refresh_token', refresh_token: user.google_refresh
    })
  });
  const d = await r.json();
  if (!d.access_token) throw new Error('Token refresh failed: ' + JSON.stringify(d));
  db.prepare('UPDATE users SET google_token=? WHERE id=?').run(d.access_token, user.id);
  return d.access_token;
}

async function gbpFetch(url, user, opts = {}) {
  let token = user.google_token;
  let res = await fetch(url, { ...opts, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', ...(opts.headers || {}) } });
  if (res.status === 401) {
    token = await refreshAccessToken(user);
    res = await fetch(url, { ...opts, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', ...(opts.headers || {}) } });
  }
  return res;
}

function requireGoogle(req, res, next) {
  if (!req.session.userId) return res.redirect(`/${req.params.lang || 'en'}/login`);
  const user = db.prepare('SELECT * FROM users WHERE id=?').get(req.session.userId);
  if (!user) return res.redirect(`/${req.params.lang || 'en'}/login`);
  req.gbUser = user;
  next();
}

// ── OAuth start ───────────────────────────────────────────────────────────────
router.get('/connect', (req, res) => {
  if (!req.session.userId) return res.redirect('/en/login');
  const state = Math.random().toString(36).slice(2) + Date.now().toString(36);
  db.prepare('UPDATE users SET google_state=? WHERE id=?').run(state, req.session.userId);
  const url = 'https://accounts.google.com/o/oauth2/v2/auth?' + new URLSearchParams({
    client_id: CLIENT_ID, redirect_uri: REDIRECT,
    response_type: 'code', scope: SCOPES,
    access_type: 'offline', prompt: 'consent',
    state
  });
  res.redirect(url);
});

// ── OAuth callback ────────────────────────────────────────────────────────────
router.get('/callback', async (req, res) => {
  if (!req.session.userId) return res.redirect('/en/login');
  const user = db.prepare('SELECT * FROM users WHERE id=?').get(req.session.userId);
  if (!user || req.query.state !== user.google_state) {
    req.flash('error', 'Invalid OAuth state.'); return res.redirect('/en/dashboard/google');
  }
  if (!req.query.code) {
    req.flash('error', 'Authorization cancelled.'); return res.redirect('/en/dashboard/google');
  }
  try {
    const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        client_id: CLIENT_ID, client_secret: CLIENT_SECRET,
        grant_type: 'authorization_code', redirect_uri: REDIRECT, code: req.query.code
      })
    });
    const td = await tokenRes.json();
    if (!td.access_token) throw new Error(JSON.stringify(td));

    db.prepare('UPDATE users SET google_token=?, google_refresh=? WHERE id=?')
      .run(td.access_token, td.refresh_token || user.google_refresh, user.id);

    // Fetch accounts to get first account_id
    const acctRes = await fetch(`${GBP}/accounts`, {
      headers: { Authorization: `Bearer ${td.access_token}` }
    });
    const acctData = await acctRes.json();
    const account = acctData.accounts?.[0];
    if (account) {
      const accountId = account.name; // e.g. "accounts/123456"
      // Fetch first location
      const locRes = await fetch(`${GBI}/${accountId}/locations?readMask=name,title`, {
        headers: { Authorization: `Bearer ${td.access_token}` }
      });
      const locData = await locRes.json();
      const location = locData.locations?.[0];
      db.prepare('UPDATE users SET google_account_id=?, google_location_id=?, google_biz_name=? WHERE id=?')
        .run(accountId, location?.name || null, location?.title || account.accountName || 'Business', user.id);
    }

    req.flash('success', 'Google Business connected!');
    res.redirect('/en/dashboard/google');
  } catch (e) {
    console.error('[google/callback]', e.message);
    req.flash('error', 'OAuth error: ' + e.message);
    res.redirect('/en/dashboard/google');
  }
});

// ── Disconnect ────────────────────────────────────────────────────────────────
router.post('/disconnect', (req, res) => {
  if (!req.session.userId) return res.redirect('/en/login');
  db.prepare('UPDATE users SET google_token=NULL,google_refresh=NULL,google_account_id=NULL,google_location_id=NULL,google_biz_name=NULL WHERE id=?')
    .run(req.session.userId);
  req.flash('success', 'Google Business disconnected.');
  res.redirect('/en/dashboard/google');
});

// ── API: list reviews ─────────────────────────────────────────────────────────
router.get('/api/reviews', requireGoogle, async (req, res) => {
  const user = req.gbUser;
  if (!user.google_location_id) return res.json({ error: 'No location connected' });
  try {
    const r = await gbpFetch(
      `https://mybusiness.googleapis.com/v4/${user.google_location_id}/reviews?pageSize=20`,
      user
    );
    const data = await r.json();
    res.json(data);
  } catch (e) {
    res.json({ error: e.message });
  }
});

// ── API: reply to review ──────────────────────────────────────────────────────
router.post('/api/reviews/:reviewId/reply', requireGoogle, async (req, res) => {
  const user = req.gbUser;
  const { comment } = req.body;
  if (!comment) return res.status(400).json({ error: 'comment required' });
  try {
    const r = await gbpFetch(
      `https://mybusiness.googleapis.com/v4/${user.google_location_id}/reviews/${req.params.reviewId}/reply`,
      user,
      { method: 'PUT', body: JSON.stringify({ comment }) }
    );
    const data = await r.json();
    res.json(data);
  } catch (e) {
    res.json({ error: e.message });
  }
});

// ── API: delete review reply ──────────────────────────────────────────────────
router.delete('/api/reviews/:reviewId/reply', requireGoogle, async (req, res) => {
  const user = req.gbUser;
  try {
    const r = await gbpFetch(
      `https://mybusiness.googleapis.com/v4/${user.google_location_id}/reviews/${req.params.reviewId}/reply`,
      user,
      { method: 'DELETE' }
    );
    res.json({ success: r.ok });
  } catch (e) {
    res.json({ error: e.message });
  }
});

// ── API: list locations ───────────────────────────────────────────────────────
router.get('/api/locations', requireGoogle, async (req, res) => {
  const user = req.gbUser;
  if (!user.google_account_id) return res.json({ error: 'No account connected' });
  try {
    const r = await gbpFetch(
      `${GBI}/${user.google_account_id}/locations?readMask=name,title,storefrontAddress`,
      user
    );
    const data = await r.json();
    res.json(data);
  } catch (e) {
    res.json({ error: e.message });
  }
});

// ── API: switch active location ───────────────────────────────────────────────
router.post('/api/locations/switch', requireGoogle, async (req, res) => {
  const { locationId, bizName } = req.body;
  if (!locationId) return res.status(400).json({ error: 'locationId required' });
  db.prepare('UPDATE users SET google_location_id=?, google_biz_name=? WHERE id=?')
    .run(locationId, bizName || locationId, req.session.userId);
  res.json({ success: true });
});

module.exports = router;
