import { db, id, now, visibleClause } from '../db.js';
import { normalizeRunPlanPayload } from '../forms/schemas.js';
import { camelRunPlan } from './mappers.js';
import { filterVisibleHostIds } from './hostModel.js';

export function listRunPlans(userId) {
  return db.prepare(`
    SELECT r.*, s.name AS script_name, g.name AS group_name,
      (SELECT COUNT(*) FROM runplan_hosts rh WHERE rh.runplan_id = r.id) AS host_count
    FROM runplans r
    JOIN scripts s ON s.id = r.script_id
    LEFT JOIN groups g ON g.id = r.group_id
    WHERE ${visibleClause('r')}
    ORDER BY r.updated_at DESC
  `).all(userId, userId).map(camelRunPlan);
}

export function createRunPlan(body, userId) {
  const payload = normalizeRunPlanPayload(body);
  const runplanId = id('run');
  db.prepare(`
    INSERT INTO runplans (id, name, description, script_id, visibility, owner_user_id, group_id, parallel, created_at, updated_at)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `).run(runplanId, payload.name, payload.description, payload.scriptId, payload.visibility, userId, payload.groupId, payload.parallel ? 1 : 0, now(), now());
  replaceRunPlanHosts(runplanId, filterVisibleHostIds(payload.hostIds, userId));
  return loadRunPlan(runplanId);
}

export function loadRunPlan(runplanId) {
  const runplan = db.prepare(`
    SELECT r.*, s.name AS script_name, g.name AS group_name,
      (SELECT COUNT(*) FROM runplan_hosts rh WHERE rh.runplan_id = r.id) AS host_count
    FROM runplans r
    JOIN scripts s ON s.id = r.script_id
    LEFT JOIN groups g ON g.id = r.group_id
    WHERE r.id = ?
  `).get(runplanId);
  if (!runplan) return null;
  const hostIds = db.prepare('SELECT host_id FROM runplan_hosts WHERE runplan_id = ? ORDER BY host_id').all(runplanId).map((row) => row.host_id);
  return { ...camelRunPlan(runplan), hostIds };
}

export function loadVisibleRunPlan(runplanId, userId) {
  const visible = db.prepare(`SELECT id FROM runplans WHERE id = ? AND ${visibleClause()}`).get(runplanId, userId, userId);
  return visible ? loadRunPlan(runplanId) : null;
}

export function updateRunPlan(runplanId, body, userId) {
  const existing = db.prepare(`SELECT * FROM runplans WHERE id = ? AND ${visibleClause()}`).get(runplanId, userId, userId);
  if (!existing) return null;
  const payload = normalizeRunPlanPayload({ ...existing, ...body, hostIds: body.hostIds || undefined });
  db.prepare(`
    UPDATE runplans SET name = ?, description = ?, script_id = ?, visibility = ?, group_id = ?, parallel = ?, updated_at = ?
    WHERE id = ?
  `).run(payload.name, payload.description, payload.scriptId, payload.visibility, payload.groupId, payload.parallel ? 1 : 0, now(), runplanId);
  if (body.hostIds) replaceRunPlanHosts(runplanId, filterVisibleHostIds(payload.hostIds, userId));
  return loadRunPlan(runplanId);
}

export function deleteRunPlan(runplanId, userId) {
  db.prepare(`DELETE FROM runplans WHERE id = ? AND ${visibleClause()}`).run(runplanId, userId, userId);
}

function replaceRunPlanHosts(runplanId, hostIds) {
  db.prepare('DELETE FROM runplan_hosts WHERE runplan_id = ?').run(runplanId);
  const stmt = db.prepare('INSERT OR IGNORE INTO runplan_hosts (runplan_id, host_id) VALUES (?, ?)');
  for (const hostId of hostIds) stmt.run(runplanId, hostId);
}
