import { applicationImportSchema, applicationSchema } from '../forms/schemas.js';
import {
  createApplication,
  deleteApplication,
  listApplications,
  loadApplication,
  recordVersionCheck,
  updateApplication
} from '../models/applicationModel.js';
import { getGraphConnection } from '../models/graphModel.js';
import { getGraphMobileApp } from '../services/graphService.js';
import { fetchLatestVersion, mapGraphAppToCatalog } from '../services/appVersionService.js';
import { runCatalogChecks } from '../services/catalogWorker.js';

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

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

export function show(req, res) {
  const application = loadApplication(req.params.id, req.user.id);
  if (!application) return res.status(404).json({ error: 'Application not found' });
  res.json(application);
}

export function update(req, res) {
  const parsed = applicationSchema.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'Invalid application payload' });
  const application = updateApplication(req.params.id, parsed.data, req.user.id);
  if (!application) return res.status(404).json({ error: 'Application not found' });
  res.json(application);
}

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

// Look up the upstream version from the configured source and store it. The
// update state (whether a newer version exists) is recomputed on read.
export async function checkUpdate(req, res) {
  const application = loadApplication(req.params.id, req.user.id);
  if (!application) return res.status(404).json({ error: 'Application not found' });
  try {
    const result = await fetchLatestVersion(application);
    const updated = recordVersionCheck(req.params.id, req.user.id, {
      latestKnownVersion: result.version || application.latestKnownVersion,
      message: result.message || ''
    });
    res.json({ application: updated, check: result });
  } catch (error) {
    recordVersionCheck(req.params.id, req.user.id, { latestKnownVersion: application.latestKnownVersion, message: error.message });
    res.status(400).json({ error: error.message });
  }
}

// Run an upstream check for every auto-check application now (admin trigger).
export async function checkAll(req, res) {
  try {
    const summary = await runCatalogChecks();
    res.json({ summary, applications: listApplications(req.user.id) });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
}

// Adopt an existing tenant Win32 app into the catalog (migration aid). Read-only
// Graph access; no write-back gate required.
export async function importFromTenant(req, res) {
  const parsed = applicationImportSchema.safeParse(req.body);
  if (!parsed.success) return res.status(400).json({ error: 'connectionId and graphAppId are required' });
  const connection = getGraphConnection(parsed.data.connectionId, req.user.id, true);
  if (!connection) return res.status(404).json({ error: 'Graph connection not found' });
  try {
    const graphApp = await getGraphMobileApp(connection, parsed.data.graphAppId);
    const mapped = mapGraphAppToCatalog(graphApp);
    const application = createApplication({
      ...mapped,
      graphConnectionId: parsed.data.connectionId,
      versionSource: 'manual',
      visibility: parsed.data.visibility,
      groupId: parsed.data.groupId,
      notes: `Adopted from Intune mobileApp ${parsed.data.graphAppId}.`
    }, req.user.id);
    res.status(201).json(application);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
}
