import { Router } from 'express';
import { env } from '../config/env.js';
import { loginUser, logoutUser, refreshUserSession, registerUser, loginWithTelegram, linkTelegramAccount, unlinkTelegramAccount, startTelegramLoginFlow, pollTelegramLoginFlow } from '../services/auth.service.js';
import { authRequired } from '../middleware/authRequired.js';
import { findUserById, updateUserBalance } from '../repositories/user.repository.js';

const router = Router();

function buildAccessCookieOptions() {
  return {
    httpOnly: true,
    secure: env.COOKIE_SECURE,
    sameSite: env.COOKIE_SAME_SITE,
    // Domain не указывается для __Host- префикса (требование RFC 6265)
    path: '/',
    maxAge: env.ACCESS_TOKEN_TTL_SEC * 1000,
  };
}

function buildRefreshCookieOptions() {
  return {
    httpOnly: true,
    secure: env.COOKIE_SECURE,
    sameSite: env.COOKIE_SAME_SITE,
    // Domain не указывается для __Host- префикса (требование RFC 6265)
    path: '/',
    maxAge: env.REFRESH_TOKEN_TTL_SEC * 1000,
  };
}

function buildCsrfCookieOptions() {
  return {
    httpOnly: false, // фронту надо прочитать и отправить в header
    secure: env.COOKIE_SECURE,
    sameSite: env.COOKIE_SAME_SITE,
    // Domain не указывается для работы с __Host- префиксом
    path: '/',
    maxAge: env.REFRESH_TOKEN_TTL_SEC * 1000,
  };
}

router.post('/login', async (req, res, next) => {
  try {
    const { email, password } = req.body;

    const result = await loginUser({
      email,
      password,
      userAgent: req.get('user-agent') || null,
      ipAddress: req.ip || null,
    });

    res.cookie(env.COOKIE_ACCESS_NAME, result.accessToken, buildAccessCookieOptions());
    res.cookie(env.COOKIE_REFRESH_NAME, result.refreshToken, buildRefreshCookieOptions());
    res.cookie(env.COOKIE_CSRF_NAME, result.csrfToken, buildCsrfCookieOptions());

    res.json({
      ok: true,
      accessToken: result.accessToken,
      user: result.user,
    });
  } catch (err) {
    next(err);
  }
});

router.post('/logout', authRequired, async (req, res, next) => {
  try {
    await logoutUser({ sessionId: req.user.sessionId });

    res.clearCookie(env.COOKIE_ACCESS_NAME, { path: '/' });
    res.clearCookie(env.COOKIE_REFRESH_NAME, { path: '/' });
    res.clearCookie(env.COOKIE_CSRF_NAME, { path: '/' });

    res.json({ ok: true });
  } catch (err) {
    next(err);
  }
});

router.post('/refresh', async (req, res, next) => {
  try {
    const refreshToken = req.cookies?.[env.COOKIE_REFRESH_NAME];

    if (!refreshToken) {
      return res.status(401).json({
        error: 'REFRESH_TOKEN_MISSING',
        message: 'Refresh token is missing',
      });
    }

    const result = await refreshUserSession({
      refreshToken,
      userAgent: req.get('user-agent') || null,
      ipAddress: req.ip || null,
    });

    res.cookie(env.COOKIE_ACCESS_NAME, result.accessToken, buildAccessCookieOptions());
    res.cookie(env.COOKIE_REFRESH_NAME, result.refreshToken, buildRefreshCookieOptions());
    res.cookie(env.COOKIE_CSRF_NAME, result.csrfToken, buildCsrfCookieOptions());

    res.json({
      ok: true,
      user: result.user,
    });
  } catch (err) {
    next(err);
  }
});

router.get('/me', authRequired, async (req, res) => {
  try {
    const dbUser = await findUserById(req.user.id);
    if (!dbUser) return res.status(401).json({ error: 'USER_NOT_FOUND' });
    res.json({
      ok: true,
      user: {
        id: dbUser.id,
        email: dbUser.email,
        displayName: dbUser.display_name,
        role: dbUser.role,
        status: dbUser.status,
        balance: Number(dbUser.balance || 0),
        createdAt: dbUser.created_at,
        sessionId: req.user.sessionId,
        telegramLinked: dbUser.telegram_id != null,
      },
    });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

router.post('/balance/update', authRequired, async (req, res) => {
  const delta = Number(req.body.delta);
  if (!delta || isNaN(delta)) return res.status(400).json({ error: 'delta required' });
  try {
    const newBalance = await updateUserBalance(req.user.id, delta);
    if (newBalance === null) return res.status(404).json({ error: 'User not found' });
    res.json({ ok: true, balance: Number(newBalance) });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

router.get('/csrf', authRequired, async (req, res) => {
  res.json({
    ok: true,
    csrfToken: req.cookies?.[env.COOKIE_CSRF_NAME] || null,
  });
});


router.post('/register', async (req, res, next) => {
  try {
    const { email, password, name } = req.body;

    const result = await registerUser({
      email,
      password,
      displayName: name || null,
      userAgent: req.get('user-agent') || null,
      ipAddress: req.ip || null,
    });

    res.cookie(env.COOKIE_ACCESS_NAME, result.accessToken, buildAccessCookieOptions());
    res.cookie(env.COOKIE_REFRESH_NAME, result.refreshToken, buildRefreshCookieOptions());
    res.cookie(env.COOKIE_CSRF_NAME, result.csrfToken, buildCsrfCookieOptions());

    res.status(201).json({
      ok: true,
      accessToken: result.accessToken,
      user: result.user,
    });
  } catch (err) {
    if (err.statusCode === 409) {
      return res.status(409).json({ ok: false, error: err.code, message: err.message });
    }
    if (err.statusCode === 400) {
      return res.status(400).json({ ok: false, error: err.code, message: err.message });
    }
    next(err);
  }
});


router.post('/telegram', async (req, res, next) => {
  try {
    const result = await loginWithTelegram({
      telegramData: req.body,
      userAgent: req.get('user-agent') || null,
      ipAddress: req.ip || null,
    });

    res.cookie(env.COOKIE_ACCESS_NAME, result.accessToken, buildAccessCookieOptions());
    res.cookie(env.COOKIE_REFRESH_NAME, result.refreshToken, buildRefreshCookieOptions());
    res.cookie(env.COOKIE_CSRF_NAME, result.csrfToken, buildCsrfCookieOptions());

    res.status(200).json({ ok: true, accessToken: result.accessToken, user: result.user });
  } catch (err) {
    const status = err.statusCode || 500;
    if (status < 500) {
      return res.status(status).json({ ok: false, error: err.code, message: err.message });
    }
    next(err);
  }
});


router.get('/telegram-widget', (req, res) => {
  res.setHeader('Content-Type', 'text/html; charset=utf-8');
  res.send('<!DOCTYPE html>\n<html lang="ru"><head><meta charset="utf-8"/><title>Telegram Auth</title><style>*{margin:0;padding:0}body{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;background:#1a1a2e;font-family:sans-serif;color:#fff}h2{font-size:24px;font-weight:700;margin-bottom:6px}p{font-size:13px;color:#aaa;margin-bottom:28px}.wrap{min-height:48px;display:flex;align-items:center}</style></head><body><h2>One Click</h2><p>Войдите через Telegram</p><div class="wrap" id="tg"></div><script>window.onTelegramAuth=function(u){if(window.opener){window.opener.postMessage({type:"telegram_auth",data:u},"*");}window.close();};</script><script async src="https://telegram.org/js/telegram-widget.js?22" data-telegram-login="One_Click_Auth_bot" data-size="large" data-radius="12" data-onauth="onTelegramAuth(user)" data-request-access="write"></script></body></html>');
});

router.post('/telegram/link', authRequired, async (req, res, next) => {
  try {
    const result = await linkTelegramAccount({ userId: req.user.id, telegramData: req.body });
    res.status(200).json(result);
  } catch (err) {
    const status = err.statusCode || 500;
    if (status < 500) return res.status(status).json({ ok: false, error: err.code, message: err.message });
    next(err);
  }
});

router.post('/telegram/unlink', authRequired, async (req, res, next) => {
  try {
    const result = await unlinkTelegramAccount(req.user.id);
    res.status(200).json(result);
  } catch (err) {
    const status = err.statusCode || 500;
    if (status < 500) return res.status(status).json({ ok: false, error: err.code, message: err.message });
    next(err);
  }
});


router.post('/telegram/start', async (req, res, next) => {
  try {
    const result = await startTelegramLoginFlow({
      intent: 'login',
      userId: null,
      ipAddress: req.ip || null,
      userAgent: req.get('user-agent') || null,
    });
    res.json({ ok: true, token: result.token, url: result.url, ttlSec: result.ttlSec });
  } catch (err) {
    const status = err.statusCode || 500;
    if (status < 500) return res.status(status).json({ ok: false, error: err.code, message: err.message });
    next(err);
  }
});

router.post('/telegram/start-link', authRequired, async (req, res, next) => {
  try {
    const result = await startTelegramLoginFlow({
      intent: 'link',
      userId: req.user.id,
      ipAddress: req.ip || null,
      userAgent: req.get('user-agent') || null,
    });
    res.json({ ok: true, token: result.token, url: result.url, ttlSec: result.ttlSec });
  } catch (err) {
    const status = err.statusCode || 500;
    if (status < 500) return res.status(status).json({ ok: false, error: err.code, message: err.message });
    next(err);
  }
});

router.get('/telegram/poll/:token', async (req, res, next) => {
  try {
    const result = await pollTelegramLoginFlow({
      token: req.params.token,
      userAgent: req.get('user-agent') || null,
      ipAddress: req.ip || null,
    });
    if (result.status === 'authenticated') {
      res.cookie(env.COOKIE_ACCESS_NAME, result.accessToken, buildAccessCookieOptions());
      res.cookie(env.COOKIE_REFRESH_NAME, result.refreshToken, buildRefreshCookieOptions());
      res.cookie(env.COOKIE_CSRF_NAME, result.csrfToken, buildCsrfCookieOptions());
      return res.json({ ok: true, status: 'authenticated', accessToken: result.accessToken, user: result.user });
    }
    if (result.status === 'linked') return res.json({ ok: true, status: 'linked' });
    if (result.status === 'pending') return res.json({ ok: true, status: 'pending' });
    if (result.status === 'consumed') return res.status(410).json({ ok: false, status: 'consumed', message: 'Эта ссылка уже использована.' });
    if (result.status === 'expired')  return res.status(410).json({ ok: false, status: 'expired',  message: 'Срок действия ссылки истёк.' });
    if (result.status === 'not_found') return res.status(404).json({ ok: false, status: 'not_found', message: 'Запрос не найден.' });
    if (result.status === 'error')    return res.status(400).json({ ok: false, status: 'error', error: result.code });
    return res.json({ ok: true, status: result.status });
  } catch (err) { next(err); }
});


export default router;