/**
 * Terminals Controller
 *
 * REST API endpoints for terminal management
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { TerminalsService } from '../services';
import { CreateTerminalDto, UpdateTerminalDto } from '../dto';

// Extend Request to include tenant info
interface AuthenticatedRequest extends Request {
  tenantId?: string;
  userId?: string;
}

export class TerminalsController {
  public router: Router;
  private service: TerminalsService;

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

  private initializeRoutes(): void {
    // Branch terminals
    this.router.get('/branch/:branchId', this.getByBranch.bind(this));
    this.router.get('/branch/:branchId/primary', this.getPrimary.bind(this));

    // Terminal CRUD
    this.router.get('/:id', this.getById.bind(this));
    this.router.post('/', this.create.bind(this));
    this.router.put('/:id', this.update.bind(this));
    this.router.delete('/:id', this.delete.bind(this));

    // Terminal actions
    this.router.get('/:id/health', this.checkHealth.bind(this));
    this.router.post('/:id/set-primary', this.setPrimary.bind(this));

    // Health check batch (for scheduled job)
    this.router.post('/health-check-batch', this.healthCheckBatch.bind(this));
  }

  /**
   * GET /payment-terminals/branch/:branchId
   * Get terminals for branch
   */
  private async getByBranch(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const terminals = await this.service.findByBranch(req.params.branchId);
      res.json({ data: terminals });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /payment-terminals/branch/:branchId/primary
   * Get primary terminal for branch
   */
  private async getPrimary(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const terminal = await this.service.findPrimaryTerminal(req.params.branchId);
      res.json({ data: terminal });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /payment-terminals/:id
   * Get terminal by ID
   */
  private async getById(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const terminal = await this.service.findById(req.params.id);

      if (!terminal) {
        res.status(404).json({ error: 'Terminal not found' });
        return;
      }

      res.json({ data: terminal });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /payment-terminals
   * Create new terminal
   */
  private async create(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const dto: CreateTerminalDto = req.body;
      const terminal = await this.service.create(req.tenantId!, dto);
      res.status(201).json({ data: terminal });
    } catch (error) {
      next(error);
    }
  }

  /**
   * PUT /payment-terminals/:id
   * Update terminal
   */
  private async update(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const dto: UpdateTerminalDto = req.body;
      const terminal = await this.service.update(req.params.id, dto);
      res.json({ data: terminal });
    } catch (error) {
      next(error);
    }
  }

  /**
   * DELETE /payment-terminals/:id
   * Delete terminal (soft delete)
   */
  private async delete(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      await this.service.delete(req.params.id);
      res.status(204).send();
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /payment-terminals/:id/health
   * Check terminal health
   */
  private async checkHealth(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const health = await this.service.checkHealth(req.params.id);
      res.json({ data: health });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /payment-terminals/:id/set-primary
   * Set terminal as primary for branch
   */
  private async setPrimary(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const terminal = await this.service.setPrimary(req.params.id);
      res.json({ data: terminal });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /payment-terminals/health-check-batch
   * Run health check on all terminals needing check (scheduled job endpoint)
   */
  private async healthCheckBatch(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const maxAgeMinutes = parseInt(req.query.maxAgeMinutes as string) || 30;
      const terminals = await this.service.findTerminalsNeedingHealthCheck(maxAgeMinutes);

      const results: { terminalId: string; status: string; message: string }[] = [];

      for (const terminal of terminals) {
        try {
          const health = await this.service.checkHealth(terminal.id);
          results.push({
            terminalId: terminal.id,
            status: health.status,
            message: health.message,
          });
        } catch (error: any) {
          results.push({
            terminalId: terminal.id,
            status: 'error',
            message: error.message,
          });
        }
      }

      res.json({ data: { checked: results.length, results } });
    } catch (error) {
      next(error);
    }
  }
}
