import { Response } from "express";
import { createLogger } from "../logging/logger";
import { AuthenticatedRequest } from "./AuthMiddleware";
import { CaldavConfig } from "@calchat/shared";
import { CaldavService } from "../services/CaldavService";

const log = createLogger("CaldavController");

export class CaldavController {
  constructor(private caldavService: CaldavService) {}

  async saveConfig(req: AuthenticatedRequest, res: Response): Promise<void> {
    try {
      const config: CaldavConfig = { userId: req.user!.userId, ...req.body };
      const response = await this.caldavService.saveConfig(config);
      res.json(response);
    } catch (error) {
      log.error(
        { err: error, userId: req.user?.userId },
        "Error saving config",
      );
      res.status(500).json({ error: "Failed to save config" });
    }
  }

  async loadConfig(req: AuthenticatedRequest, res: Response): Promise<void> {
    try {
      const config = await this.caldavService.getConfig(req.user!.userId);
      if (!config) {
        res.status(404).json({ error: "No CalDAV config found" });
        return;
      }
      // Don't expose the password to the client
      res.json(config);
    } catch (error) {
      log.error(
        { err: error, userId: req.user?.userId },
        "Error loading config",
      );
      res.status(500).json({ error: "Failed to load config" });
    }
  }

  async deleteConfig(req: AuthenticatedRequest, res: Response): Promise<void> {
    try {
      await this.caldavService.deleteConfig(req.user!.userId);
      res.status(204).send();
    } catch (error) {
      log.error(
        { err: error, userId: req.user?.userId },
        "Error deleting config",
      );
      res.status(500).json({ error: "Failed to delete config" });
    }
  }

  async pullEvents(req: AuthenticatedRequest, res: Response): Promise<void> {
    try {
      const events = await this.caldavService.pullEvents(req.user!.userId);
      res.json(events);
    } catch (error) {
      log.error(
        { err: error, userId: req.user?.userId },
        "Error pulling events",
      );
      res.status(500).json({ error: "Failed to pull events" });
    }
  }

  async pushEvents(req: AuthenticatedRequest, res: Response): Promise<void> {
    try {
      await this.caldavService.pushAll(req.user!.userId);
      res.status(204).send();
    } catch (error) {
      log.error(
        { err: error, userId: req.user?.userId },
        "Error pushing events",
      );
      res.status(500).json({ error: "Failed to push events" });
    }
  }

  async pushEvent(req: AuthenticatedRequest, res: Response): Promise<void> {
    try {
      const event = await this.caldavService.findEventByCaldavUUID(
        req.user!.userId,
        req.params.caldavUUID,
      );
      if (!event) {
        res.status(404).json({ error: "Event not found" });
        return;
      }
      await this.caldavService.pushEvent(req.user!.userId, event);
      res.status(204).send();
    } catch (error) {
      log.error(
        { err: error, userId: req.user?.userId },
        "Error pushing event",
      );
      res.status(500).json({ error: "Failed to push event" });
    }
  }
}
