import { apiRoute } from '@/lib/api/handler'
import { ApiError, ERROR_CODES } from '@/lib/api/errors'
import { demoBaseTimestamp } from '@/lib/demo/config'
import { solveGridFlow } from '@/lib/services/physics-grid-service'

export const dynamic = 'force-dynamic'

/**
 * The solved flow, by either method.
 *
 * `?mode=ac` runs Newton–Raphson and returns voltage magnitudes, angles, reactive flow and
 * a convergence report. `?mode=fast` runs the 4.2 demand allocation. Both say which they
 * are; neither is presented as the other.
 *
 * The AC solve is the most expensive request the platform accepts, so it is rate-limited
 * well below the fast path.
 */
export const GET = apiRoute({ permission: 'twin.read', limit: 60 }, async ({ searchParams }) => {
  const mode = searchParams.get('mode') === 'ac' ? 'ac' : 'fast'
  const ts = searchParams.get('clock') === 'demo' ? demoBaseTimestamp() : undefined
  const outages = (searchParams.get('outages') ?? '').split(',').map((s) => s.trim()).filter(Boolean)

  const solution = await solveGridFlow({
    twinCode: searchParams.get('twin') ?? undefined,
    mode,
    ts,
    outages: outages.length > 0 ? outages : undefined,
    slackCode: searchParams.get('slack') ?? undefined,
    // A horizon makes the answer a prediction of a flow. The payload says so; the caller
    // does not have to remember what it asked for.
    offsetMin: Math.min(720, Math.max(0, Number(searchParams.get('offset')) || 0)),
  })
  if (!solution) throw new ApiError(ERROR_CODES.notFound)

  return solution
})
