/**
 * Auth Routes
 *
 * GitHub OAuth authentication endpoints.
 */

import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
import type { AppContext } from '../router.js';
import { getGitHubAuth } from '../../auth/github.js';
import { getTokenManager } from '../../auth/manager.js';
import { DEFAULT_SCOPES, type LoginResponse, type LoginPollResponse } from '../../auth/types.js';

export const authRoutes = new Hono<AppContext>();

/**
 * Login request schema
 */
const LoginRequestSchema = z.object({
  scopes: z.array(z.string()).optional(),
});

/**
 * POST /auth/login - Start OAuth device flow
 *
 * Returns user_code and verification_uri for user to complete in browser.
 */
authRoutes.post('/login', zValidator('json', LoginRequestSchema.optional()), async (c) => {
  const body = c.req.valid('json');
  const scopes = body?.scopes ?? DEFAULT_SCOPES;

  try {
    const auth = getGitHubAuth();
    const deviceCode = await auth.requestDeviceCode(scopes);

    const response: LoginResponse = {
      userCode: deviceCode.user_code,
      verificationUri: deviceCode.verification_uri,
      expiresIn: deviceCode.expires_in,
      interval: deviceCode.interval,
    };

    return c.json(response);
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Failed to start login' },
      500
    );
  }
});

/**
 * POST /auth/login/poll/:userCode - Poll for OAuth completion
 *
 * Client should call this repeatedly until status is 'success' or 'error'.
 */
authRoutes.post('/login/poll/:userCode', async (c) => {
  const { userCode } = c.req.param();

  try {
    const auth = getGitHubAuth();
    const result = await auth.pollByUserCode(userCode);

    const response: LoginPollResponse = {
      status: result.status,
      username: result.config?.username,
      error: result.error,
    };

    return c.json(response);
  } catch (error) {
    return c.json(
      {
        status: 'error' as const,
        error: error instanceof Error ? error.message : 'Poll failed',
      },
      500
    );
  }
});

/**
 * POST /auth/logout - Clear stored credentials
 */
authRoutes.post('/logout', async (c) => {
  try {
    const auth = getGitHubAuth();
    const success = await auth.logout();

    return c.json({
      success,
      message: success ? 'Logged out successfully' : 'No credentials to clear',
    });
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Logout failed' },
      500
    );
  }
});

/**
 * GET /auth/status - Get authentication status
 */
authRoutes.get('/status', async (c) => {
  try {
    const tokenManager = getTokenManager();
    const status = await tokenManager.getStatus();

    return c.json(status);
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Failed to get status' },
      500
    );
  }
});

/**
 * GET /auth/token - Get current token (for debugging/internal use)
 *
 * Returns masked token for security.
 */
authRoutes.get('/token', async (c) => {
  try {
    const tokenManager = getTokenManager();
    const token = await tokenManager.getToken();

    if (!token) {
      return c.json({ hasToken: false });
    }

    // Mask token for security
    const masked = token.slice(0, 4) + '****' + token.slice(-4);

    return c.json({
      hasToken: true,
      masked,
      length: token.length,
    });
  } catch (error) {
    return c.json(
      { error: error instanceof Error ? error.message : 'Failed to get token' },
      500
    );
  }
});
