// src/controllers/api/v1/drone.ts
// Copyright (C) 2026 Robert Colbert <rob.colbert@openplatform.us>
// All Rights Reserved

import { Request, Response } from "express";
import { DroneStatus } from "@gadget/api";
import DroneService from "../../../services/drone.ts";
import UserService from "../../../services/user.ts";

import { DtpController } from "../../../lib/controller.js";
import { populateDroneRegistrationById } from "@/controllers/lib/populators.js";

export class DroneApiControllerV1 extends DtpController {
  get name(): string {
    return "DroneApiControllerV1";
  }
  get slug(): string {
    return "ctrl:drone:v1";
  }
  get route(): string {
    return "/drone";
  }

  constructor() {
    super();
  }

  async start(): Promise<void> {
    const requireUser = this.requireUser();
    const multer = this.createMulter(this.slug, {});

    this.router.param("registrationId", populateDroneRegistrationById(this));

    this.router.post(
      "/registration",
      multer.none(),
      this.postRegistration.bind(this),
    );

    this.router.put(
      "/registration/:registrationId/status",
      this.putRegistrationStatus.bind(this),
    );

    this.router.get(
      "/registration",
      requireUser,
      this.getRegistrations.bind(this),
    );

    this.router.get(
      "/registration/manager",
      requireUser,
      this.getManagerRegistrations.bind(this),
    );

    this.router.post(
      "/registration/:registrationId/terminate",
      requireUser,
      this.postTerminate.bind(this),
    );

    this.router.delete(
      "/registration/:registrationId",
      this.deleteRegistration.bind(this),
    );
  }

  async postRegistration(req: Request, res: Response): Promise<void> {
    try {
      const user = await UserService.authenticate(
        req.body.email,
        req.body.password,
      );
      const registration = await DroneService.register(user, req.body);
      res.status(200).json({
        success: true,
        data: registration,
      });
    } catch (error) {
      this.log.error("failed to process drone registration", { error });
      res.status((error as Error).statusCode || 500).json({
        success: false,
        message: (error as Error).message,
      });
    }
  }

  async putRegistrationStatus(req: Request, res: Response): Promise<void> {
    try {
      await DroneService.setStatus(res.locals.registration, req.body.status);
      res.status(200).json({ success: true });
    } catch (error) {
      this.log.error("failed to update drone status", {
        _id: res.locals.registration._id,
        error,
      });
      res.status((error as Error).statusCode || 500).json({
        success: false,
        message: (error as Error).message,
      });
    }
  }

  async getRegistrations(req: Request, res: Response): Promise<void> {
    try {
      const registrations = await DroneService.getForUser(req.user, [
        DroneStatus.Starting,
        DroneStatus.Offline,
      ]);
      res.status(200).json({
        success: true,
        data: registrations,
      });
    } catch (error) {
      this.log.error("failed to present drone registrations for User", {
        error,
      });
      res.status((error as Error).statusCode || 500).json({
        success: false,
        message: (error as Error).message,
      });
    }
  }

  async getManagerRegistrations(req: Request, res: Response): Promise<void> {
    try {
      const registrations = await DroneService.getForManager(req.user);
      res.status(200).json({
        success: true,
        data: registrations,
      });
    } catch (error) {
      this.log.error("failed to present drone manager registrations for User", {
        error,
      });
      res.status((error as Error).statusCode || 500).json({
        success: false,
        message: (error as Error).message,
      });
    }
  }

  async postTerminate(req: Request, res: Response): Promise<void> {
    try {
      const result = await DroneService.requestTermination(
        req.params.registrationId as string,
      );
      res.status(200).json({
        success: result.success,
        message: result.message,
      });
    } catch (error) {
      this.log.error("failed to terminate drone", {
        registrationId: req.params.registrationId,
        error,
      });
      res.status((error as Error).statusCode || 500).json({
        success: false,
        message: (error as Error).message,
      });
    }
  }

  async deleteRegistration(_req: Request, res: Response): Promise<void> {
    try {
      await DroneService.unregister(res.locals.registration);
      res.status(200).json({ success: true });
    } catch (error) {
      this.log.error("failed to unregister drone", { error });
      res.status((error as Error).statusCode || 500).json({
        success: false,
        message: (error as Error).message,
      });
    }
  }
}

export default DroneApiControllerV1;
