/**
 * Device Registration Controller
 *
 * REST API endpoints for mobile device registration and app configuration
 *
 * @module Mobile
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { DeviceRegistrationService, RegisterDeviceDto } from '../services/device-registration.service';

interface AuthenticatedRequest extends Request {
  tenantId?: string;
  userId?: string;
}

export class DeviceRegistrationController {
  public router: Router;
  private service: DeviceRegistrationService;

  constructor(dataSource: DataSource) {
    this.router = Router();
    this.service = new DeviceRegistrationService(dataSource);
    this.initializeRoutes();
  }

  private initializeRoutes(): void {
    // Device registration
    this.router.post('/register', this.registerDevice.bind(this));
    this.router.post('/unregister/:deviceId', this.unregisterDevice.bind(this));
    this.router.get('/status/:deviceId', this.checkDeviceStatus.bind(this));
    this.router.put('/info/:sessionId', this.updateDeviceInfo.bind(this));

    // App configuration
    this.router.get('/config', this.getAppConfig.bind(this));

    // User devices
    this.router.get('/user/:userId/devices', this.getUserDevices.bind(this));
    this.router.post('/user/:userId/revoke/:deviceId', this.revokeDeviceAccess.bind(this));
    this.router.post('/user/:userId/revoke-all', this.revokeAllDevices.bind(this));
  }

  /**
   * POST /mobile/devices/register
   * Register a device
   */
  private async registerDevice(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const dto: RegisterDeviceDto = req.body;
      const result = await this.service.registerDevice(
        { tenantId: req.tenantId! },
        dto
      );

      res.status(201).json({ data: result });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /mobile/devices/unregister/:deviceId
   * Unregister a device
   */
  private async unregisterDevice(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await this.service.unregisterDevice(
        { tenantId: req.tenantId! },
        req.params.deviceId
      );
      res.status(204).send();
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /mobile/devices/status/:deviceId
   * Check device registration status
   */
  private async checkDeviceStatus(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const status = await this.service.checkDeviceStatus(
        { tenantId: req.tenantId! },
        req.params.deviceId
      );
      res.json({ data: status });
    } catch (error) {
      next(error);
    }
  }

  /**
   * PUT /mobile/devices/info/:sessionId
   * Update device info
   */
  private async updateDeviceInfo(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const session = await this.service.updateDeviceInfo(
        { tenantId: req.tenantId! },
        req.params.sessionId,
        req.body
      );
      res.json({
        data: {
          deviceId: session.deviceId,
          platform: session.platform,
          osVersion: session.osVersion,
          appVersion: session.appVersion,
        },
      });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /mobile/devices/config
   * Get app configuration
   */
  private async getAppConfig(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const platform = req.query.platform as string;
      const config = await this.service.getAppConfig(
        { tenantId: req.tenantId! },
        platform
      );
      res.json({ data: config });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /mobile/devices/user/:userId/devices
   * Get registered devices for user
   */
  private async getUserDevices(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const devices = await this.service.getUserDevices(
        { tenantId: req.tenantId! },
        req.params.userId
      );
      res.json({ data: devices });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /mobile/devices/user/:userId/revoke/:deviceId
   * Revoke device access for user
   */
  private async revokeDeviceAccess(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await this.service.revokeDeviceAccess(
        { tenantId: req.tenantId! },
        req.params.userId,
        req.params.deviceId
      );
      res.status(204).send();
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /mobile/devices/user/:userId/revoke-all
   * Revoke all device access for user
   */
  private async revokeAllDevices(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const count = await this.service.revokeAllDevices(
        { tenantId: req.tenantId! },
        req.params.userId
      );
      res.json({ data: { revoked: count } });
    } catch (error) {
      next(error);
    }
  }
}
