/**
 * POST /api/analyzer/itglue/applications/:id/revert/:writeId
 *
 * Reverts a previously committed write by re-applying its before_value.
 * Implementation: insert a NEW itglue_writes row with reversed before/after,
 * call IT Glue PATCH with the original before_value, then mark the original
 * row status='reverted'. Audit log captures both rows.
 */

import { NextRequest, NextResponse } from 'next/server';
import { requirePermission } from '@/lib/auth-utils';
import postgresClient from '@/lib/services/postgres-client';
import {
  createPendingWrite,
  fieldNameToTraitKey,
  getWriteById,
  markWriteCommitted,
  markWriteFailed,
  markWriteReverted,
} from '@/lib/services/analyzer/asset-audit/persistence';
import { getITGlueClient } from '@/lib/services/itglue-client';
import { getITGlueSyncService } from '@/lib/services/itglue-sync-service';
import { audit } from '@/lib/services/audit';

interface AssetRow {
  id: string;
  traits: Record<string, unknown>;
}

export async function POST(
  _request: NextRequest,
  { params }: { params: Promise<{ id: string; writeId: string }> }
) {
  const { session, error } = await requirePermission('itglue', 'write');
  if (error) return error;

  const { id: assetId, writeId } = await params;
  const userId =
    (session?.user as { id: string; email?: string } | undefined)?.id ?? null;
  const userEmail =
    (session?.user as { id: string; email?: string } | undefined)?.email ??
    undefined;

  const original = await getWriteById(writeId);
  if (!original) {
    return NextResponse.json({ error: 'Write not found' }, { status: 404 });
  }
  if (original.asset_id !== assetId) {
    return NextResponse.json(
      { error: 'Write does not reference this asset' },
      { status: 400 }
    );
  }
  if (original.status === 'reverted') {
    return NextResponse.json(
      { error: 'Write already reverted' },
      { status: 400 }
    );
  }
  if (original.status !== 'committed') {
    return NextResponse.json(
      { error: `Cannot revert a write in status '${original.status}'` },
      { status: 400 }
    );
  }

  // Read current asset traits to merge cleanly.
  const assetRes = await postgresClient.query<AssetRow>(
    `SELECT id::text AS id, traits FROM itg_flexible_assets WHERE id = $1 LIMIT 1`,
    [assetId]
  );
  if (assetRes.rowCount === 0) {
    return NextResponse.json({ error: 'Asset not found' }, { status: 404 });
  }
  const traits = assetRes.rows[0].traits;
  const traitKey = fieldNameToTraitKey(original.field_name);

  // Build the revert: swap original's before/after; the new "after" value is
  // the original's "before".
  const revertRow = await createPendingWrite({
    audit_id: original.audit_id,
    asset_type: 'flexible_asset',
    asset_id: assetId,
    field_name: original.field_name,
    before_value: original.after_value,
    after_value: original.before_value,
    performed_by_user_id: userId,
    source_evidence: { reverts_write_id: original.id },
  });

  const merged: Record<string, unknown> = {
    ...traits,
    [traitKey]: original.before_value,
  };

  try {
    const client = getITGlueClient();
    const updated = await client.updateFlexibleAsset(assetId, merged);

    await markWriteCommitted(revertRow.id, updated);
    await markWriteReverted(original.id);

    try {
      await getITGlueSyncService().refreshFlexibleAssetById(assetId);
    } catch (refreshErr) {
      console.warn(
        `[itglue-revert] mirror refresh failed for asset ${assetId}:`,
        refreshErr instanceof Error ? refreshErr.message : refreshErr
      );
    }

    await audit.log({
      userId: userId ?? undefined,
      userEmail,
      action: 'itglue.revert',
      resource: 'flexible_asset',
      resourceId: assetId,
      details: {
        revert_write_id: revertRow.id,
        original_write_id: original.id,
        field_name: original.field_name,
        before: original.after_value,
        after: original.before_value,
      },
    });

    return NextResponse.json({
      writeId: revertRow.id,
      revertedWriteId: original.id,
      status: 'committed',
      asset: updated,
    });
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err);
    await markWriteFailed(revertRow.id, message);
    return NextResponse.json(
      {
        writeId: revertRow.id,
        status: 'failed',
        error: 'IT Glue revert failed',
        message,
      },
      { status: 502 }
    );
  }
}
