import { hostSchema, vcenterConnectionSchema, vcenterImportSchema, vcenterPreviewSchema } from '../forms/schemas.js';
import { createHost, deleteHost, findVisibleHostByIdentity, listHosts, updateHost } from '../models/hostModel.js';
import { createHostGroup, deleteHostGroup, getVisibleHostGroup, listHostGroups, syncHostGroup, syncDynamicHostGroups, updateHostGroup } from '../models/hostGroupModel.js';
import {
  createVCenterConnection,
  deleteVCenterConnection,
  getVCenterConnection,
  listVCenterConnections,
  recordVCenterConnectionTest,
  updateVCenterConnection
} from '../models/vcenterConnectionModel.js';
import { buildHostPayloadFromVm, previewVCenterHosts, testVCenterConnection, vcenterStatus } from '../services/vcenterService.js';

export function index(req, res) {
  res.json(listHosts(req.user.id));
}

export function create(req, res) {
  const parsed = hostSchema.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'Invalid host payload' });
  res.status(201).json(createHost(parsed.data, req.user.id));
}

export function update(req, res) {
  const host = updateHost(req.params.id, req.body, req.user.id);
  if (!host) return res.status(404).json({ error: 'Host not found' });
  res.json(host);
}

export function destroy(req, res) {
  deleteHost(req.params.id, req.user.id);
  res.status(204).end();
}

export function listGroups(req, res) {
  res.json(listHostGroups(req.user.id));
}

export function createGroup(req, res) {
  try {
    res.status(201).json(createHostGroup(req.body, req.user.id));
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
}

export function updateGroup(req, res) {
  try {
    const group = updateHostGroup(req.params.groupId, req.body, req.user.id);
    if (!group) return res.status(404).json({ error: 'Host group not found' });
    res.json(group);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
}

export function deleteGroup(req, res) {
  deleteHostGroup(req.params.groupId, req.user.id);
  res.status(204).end();
}

export function syncGroup(req, res) {
  const group = getVisibleHostGroup(req.params.groupId, req.user.id);
  if (!group) return res.status(404).json({ error: 'Host group not found' });
  if (group.mode !== 'dynamic') return res.status(400).json({ error: 'Only dynamic host groups can be synced.' });
  res.json(syncHostGroup(group.id));
}

export function syncGroups(req, res) {
  res.json(syncDynamicHostGroups());
}

export function vcenterImportStatus(req, res) {
  res.json({
    defaultConnection: vcenterStatus(),
    connections: listVCenterConnections(req.user.id)
  });
}

export async function previewVCenterImport(req, res) {
  const parsed = vcenterPreviewSchema.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'Invalid vCenter preview payload' });
  try {
    const connection = parsed.data.connectionId ? getVCenterConnection(parsed.data.connectionId, req.user.id, true) : null;
    if (parsed.data.connectionId && !connection) return res.status(404).json({ error: 'VMware connection not found' });
    res.json(await previewVCenterHosts({ ...parsed.data, connection }));
  } catch (err) {
    res.status(err.statusCode || 502).json({ error: err.message, trace: err.trace || [] });
  }
}

export async function importVCenterHosts(req, res) {
  const parsed = vcenterImportSchema.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'Invalid vCenter import payload' });
  try {
    const connection = parsed.data.connectionId ? getVCenterConnection(parsed.data.connectionId, req.user.id, true) : null;
    if (parsed.data.connectionId && !connection) return res.status(404).json({ error: 'VMware connection not found' });
    const preview = await previewVCenterHosts({ ...parsed.data, connection });
    const selected = new Set(parsed.data.vmIds || []);
    const candidates = selected.size
      ? preview.candidates.filter((candidate) => selected.has(candidate.id))
      : preview.candidates;
    const imported = [];
    const skipped = [];

    for (const candidate of candidates) {
      const hostPayload = buildHostPayloadFromVm(candidate, parsed.data);
      const existing = findVisibleHostByIdentity(hostPayload, req.user.id);
      if (existing) {
        skipped.push({ vm: candidate, reason: `Existing host matched ${existing.name}` });
        continue;
      }
      imported.push(createHost(hostPayload, req.user.id));
    }

    res.status(201).json({ imported, skipped, scanned: preview.count, trace: preview.trace || [] });
  } catch (err) {
    res.status(err.statusCode || 502).json({ error: err.message, trace: err.trace || [] });
  }
}

export function listVCenterConnectionRecords(req, res) {
  res.json(listVCenterConnections(req.user.id));
}

export function createVCenterConnectionRecord(req, res) {
  const parsed = vcenterConnectionSchema.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'Invalid VMware connection payload' });
  try {
    res.status(201).json(createVCenterConnection(parsed.data, req.user.id));
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
}

export function updateVCenterConnectionRecord(req, res) {
  const parsed = vcenterConnectionSchema.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'Invalid VMware connection payload' });
  try {
    const connection = updateVCenterConnection(req.params.connectionId, parsed.data, req.user.id);
    if (!connection) return res.status(404).json({ error: 'VMware connection not found' });
    res.json(connection);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
}

export function deleteVCenterConnectionRecord(req, res) {
  deleteVCenterConnection(req.params.connectionId, req.user.id);
  res.status(204).end();
}

export async function testVCenterConnectionRecord(req, res) {
  const connection = getVCenterConnection(req.params.connectionId, req.user.id, true);
  if (!connection) return res.status(404).json({ error: 'VMware connection not found' });
  try {
    const result = await testVCenterConnection(connection);
    recordVCenterConnectionTest(req.params.connectionId, 'success', result.message);
    res.json(result);
  } catch (err) {
    recordVCenterConnectionTest(req.params.connectionId, 'failed', err.message);
    res.status(err.statusCode || 502).json({ error: err.message, trace: err.trace || [] });
  }
}
