import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import type { AuthService } from '../auth/auth-service.js';
import type { BetterAuthInstance } from '../auth/better-auth-config.js';
import type { ContainerManager } from '../k8s/container-manager.js';
import type { UserService } from '../db/user-service.js';

export interface AuthRoutesConfig {
  authService: AuthService;
  betterAuth: BetterAuthInstance;
  containerManager: ContainerManager;
  userService: UserService;
}

/**
 * Authentication routes for user registration, login, and passkey management
 */
export class AuthRoutes {
  private config: AuthRoutesConfig;

  constructor(config: AuthRoutesConfig) {
    this.config = config;
  }

  /**
   * Register authentication routes
   */
  register(app: FastifyInstance): void {
    // Better Auth provides built-in routes via its handler
    // Mount Better Auth's automatic routes at /api/auth/*
    app.all('/api/auth/*', async (request: FastifyRequest, reply: FastifyReply) => {
      // Better Auth handler processes the request
      const response = await this.config.betterAuth.handler(request.raw as any);

      // Forward the response to Fastify
      reply.status(response.status);
      response.headers.forEach((value, key) => {
        reply.header(key, value);
      });
      return response.body;
    });

    // Custom routes for integration with existing system

    /**
     * Register new user with email and password
     * POST /auth/register
     */
    app.post(
      '/auth/register',
      {
        schema: {
          body: {
            type: 'object',
            required: ['email', 'password'],
            properties: {
              email: { type: 'string', format: 'email' },
              password: { type: 'string', minLength: 8 },
              name: { type: 'string' },
            },
          },
        },
      },
      async (request, reply) => {
        const { email, password, name } = request.body as {
          email: string;
          password: string;
          name?: string;
        };

        const result = await this.config.authService.createUser(email, password, name);

        if (result.error) {
          return reply.code(400).send({
            error: result.error,
          });
        }

        // Ensure user has a license
        await this.config.authService.ensureUserLicense(result.userId, email);

        // Warm up the sandbox container so it's likely ready by first login
        this.config.userService.getUserLicense(result.userId).then((license) => {
          if (license) {
            this.config.containerManager.ensureContainerRunning(result.userId, license.license, false)
              .catch((err) => app.log.warn({ err, userId: result.userId }, 'Container warmup on registration failed'));
          }
        }).catch((err) => app.log.warn({ err, userId: result.userId }, 'Failed to fetch license for container warmup'));

        // Auto sign in after registration
        const signInResult = await this.config.authService.signIn(email, password);

        if (signInResult.error) {
          return reply.code(500).send({
            error: 'User created but auto sign-in failed',
          });
        }

        return {
          success: true,
          userId: result.userId,
          token: signInResult.token,
        };
      }
    );

    /**
     * Sign in with email and password
     * POST /auth/login
     */
    app.post(
      '/auth/login',
      {
        schema: {
          body: {
            type: 'object',
            required: ['email', 'password'],
            properties: {
              email: { type: 'string', format: 'email' },
              password: { type: 'string' },
            },
          },
        },
      },
      async (request, reply) => {
        const { email, password } = request.body as {
          email: string;
          password: string;
        };

        const result = await this.config.authService.signIn(email, password);

        if (result.error) {
          return reply.code(401).send({
            error: result.error,
          });
        }

        return {
          success: true,
          userId: result.userId,
          token: result.token,
        };
      }
    );

    /**
     * Sign out
     * POST /auth/logout
     */
    app.post('/auth/logout', async (request, reply) => {
      const token = this.extractBearerToken(request);

      if (!token) {
        return reply.code(401).send({
          error: 'No token provided',
        });
      }

      const result = await this.config.authService.signOut(token);

      return {
        success: result.success,
      };
    });

    /**
     * Get current session
     * GET /auth/session
     */
    app.get('/auth/session', async (request, reply) => {
      const token = this.extractBearerToken(request);

      if (!token) {
        return reply.code(401).send({
          error: 'No token provided',
        });
      }

      const session = await this.config.authService.getSession(token);

      if (!session) {
        return reply.code(401).send({
          error: 'Invalid or expired session',
        });
      }

      return {
        user: session.user,
        session: session.session,
      };
    });

    // Passkey support disabled for now (beta - email/password only)
    // /**
    //  * Passkey registration - generate options
    //  * POST /auth/passkey/register/options
    //  */
    // app.post('/auth/passkey/register/options', async (request, reply) => {
    //   const token = this.extractBearerToken(request);
    //
    //   if (!token) {
    //     return reply.code(401).send({
    //       error: 'Authentication required',
    //     });
    //   }
    //
    //   try {
    //     const options = await this.config.authService.registerPasskey('', token);
    //     return options;
    //   } catch (error: any) {
    //     app.log.error({ error }, 'Passkey registration options failed');
    //     return reply.code(500).send({
    //       error: error.message || 'Failed to generate passkey options',
    //     });
    //   }
    // });
    //
    // /**
    //  * Passkey authentication
    //  * POST /auth/passkey/authenticate
    //  */
    // app.post(
    //   '/auth/passkey/authenticate',
    //   {
    //     schema: {
    //       body: {
    //         type: 'object',
    //         required: ['credential'],
    //       },
    //     },
    //   },
    //   async (request, reply) => {
    //     const { credential } = request.body as { credential: any };
    //
    //     const result = await this.config.authService.authenticatePasskey(credential);
    //
    //     if (result.error) {
    //       return reply.code(401).send({
    //         error: result.error,
    //       });
    //     }
    //
    //     return {
    //       success: true,
    //       userId: result.userId,
    //       token: result.token,
    //     };
    //   }
    // );

    /**
     * Health check for auth system
     * GET /auth/health
     */
    app.get('/auth/health', async () => {
      return {
        status: 'ok',
        timestamp: new Date().toISOString(),
        authProvider: 'better-auth',
      };
    });
  }

  /**
   * Extract bearer token from request headers
   */
  private extractBearerToken(request: FastifyRequest): string | null {
    const auth = request.headers.authorization;
    if (!auth || !auth.startsWith('Bearer ')) {
      return null;
    }
    return auth.substring(7);
  }
}
