import type { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import * as connectorService from '../services/connector.service.js';
import { AppError } from '../middlewares/error.middleware.js';

const heartbeatSchema = z.object({
  version: z.string(),
  uptimeSeconds: z.number().optional().default(0),
  postgresPingMs: z.number().optional().default(0),
  pgVersion: z.string().optional(),
  lastMigration: z.string().optional(),
  status: z.string().optional(),
  errorMsg: z.string().optional(),
});

// Called by the connector Docker container, NOT by browser users
export async function heartbeat(req: Request, res: Response, next: NextFunction) {
  try {
    const authHeader = req.headers.authorization;
    if (!authHeader?.startsWith('Bearer ')) {
      return res.status(401).json({ message: 'Token requerido' });
    }

    const token = authHeader.split(' ')[1];
    const tenantId = await connectorService.verifyConnectorToken(token);
    if (!tenantId) {
      return res.status(401).json({ message: 'Token inválido' });
    }

    const data = heartbeatSchema.parse(req.body);
    await connectorService.recordHeartbeat(tenantId, data);

    return res.json({ ok: true });
  } catch (err: any) {
    if (err instanceof z.ZodError) return next(new AppError(400, err.errors[0].message));
    return next(err);
  }
}

// Called by authenticated tenant owner to provision or check connector
export async function provision(req: Request, res: Response, next: NextFunction) {
  try {
    const tenantId = req.viewingTenantId || req.user!.tenantId;
    const result = await connectorService.provisionConnector(tenantId);
    return res.status(201).json(result);
  } catch (err: any) {
    if (err.message?.includes('no encontrado')) return next(new AppError(404, err.message));
    return next(err);
  }
}

export async function status(req: Request, res: Response, next: NextFunction) {
  try {
    const tenantId = req.viewingTenantId || req.user!.tenantId;
    const result = await connectorService.getConnectorStatus(tenantId);
    return res.json(result);
  } catch (err) { return next(err); }
}
