import{CodeBlock as a}from"@contractspec/lib.design-system";import i from"@contractspec/lib.ui-link";import{ChevronRight as n}from"lucide-react";import{jsx as e,jsxs as t}from"react/jsx-runtime";function s(){return t("div",{className:"space-y-8",children:[t("div",{className:"space-y-2",children:[e("h1",{className:"font-bold text-4xl",children:"Your First Operation"}),e("p",{className:"text-lg text-muted-foreground",children:"Build a payment capture operation with policy enforcement in under 10 minutes."})]}),t("div",{className:"space-y-6",children:[t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"What you'll build"}),e("p",{className:"text-muted-foreground",children:"A real-world payment processing operation that validates input, enforces business rules, integrates with Stripe, and audits every transaction. This is production-ready code, not a toy example."})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"1. Define the operation spec"}),t("p",{className:"text-muted-foreground",children:["Create ",e("code",{children:"lib/specs/billing/capture-payment.ts"}),":"]}),e(a,{language:"typescript",filename:"lib/specs/billing/capture-payment.ts",code:`import { defineCommand } from '@contractspec/lib.contracts-spec';
import { SchemaModel, ScalarTypeEnum } from '@contractspec/lib.schema';

const CapturePaymentInput = new SchemaModel({
  name: 'CapturePaymentInput',
  fields: {
    invoiceId: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
    amount: { type: ScalarTypeEnum.PositiveNumber(), isOptional: false },
    currency: { type: ScalarTypeEnum.String(), isOptional: false },
    paymentMethodId: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
  },
});

const PaymentResult = new SchemaModel({
  name: 'PaymentResult',
  fields: {
    transactionId: { type: ScalarTypeEnum.String(), isOptional: false },
    status: { type: ScalarTypeEnum.String(), isOptional: false },
    receiptUrl: { type: ScalarTypeEnum.String(), isOptional: true },
  },
});

export const CapturePayment = defineCommand({
  meta: {
    key: 'billing.capturePayment',
    version: '1.0.0',
    description: 'Process a payment for an invoice',
    goal: 'Capture funds from customer payment method',
    context: 'Called when customer confirms purchase',
    owners: ['team-billing'],
    tags: ['payments', 'stripe', 'critical'],
    stability: 'stable',
  },
  io: {
    input: CapturePaymentInput,
    output: PaymentResult,
  },
  policy: {
    auth: 'user',
    rules: [
      { resource: 'invoice', action: 'pay', condition: 'owner' },
    ],
  },
});`})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"2. Implement the handler"}),t("p",{className:"text-muted-foreground",children:["Create ",e("code",{children:"lib/handlers/billing/capture-payment.ts"}),":"]}),e(a,{language:"typescript",filename:"lib/handlers/billing/capture-payment.ts",code:`import { CapturePayment } from '@/lib/specs/billing/capture-payment';
import { stripe } from '@/lib/integrations/stripe';
import { db } from '@/lib/db';

export async function handleCapturePayment(input, ctx) {
  // 1. Verify invoice exists and belongs to user
  const invoice = await db.invoice.findUnique({
    where: { id: input.invoiceId, userId: ctx.userId },
  });

  if (!invoice) throw new Error('Invoice not found');
  if (invoice.status === 'paid') throw new Error('Already paid');

  // 2. Create Stripe payment intent
  const paymentIntent = await stripe.paymentIntents.create({
    amount: Math.round(input.amount * 100),
    currency: input.currency,
    payment_method: input.paymentMethodId,
    confirm: true,
    metadata: { invoiceId: input.invoiceId },
  });

  // 3. Update invoice status
  await db.invoice.update({
    where: { id: input.invoiceId },
    data: {
      status: 'paid',
      paidAt: new Date(),
      transactionId: paymentIntent.id,
    },
  });

  return {
    transactionId: paymentIntent.id,
    status: paymentIntent.status,
    receiptUrl: paymentIntent.charges.data[0]?.receipt_url,
  };
}`})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"3. Register and serve"}),t("p",{className:"text-muted-foreground",children:["Wire it up in ",e("code",{children:"lib/registry.ts"})," and"," ",e("code",{children:"app/api/ops/[...route]/route.ts"}),":"]}),e(a,{language:"typescript",filename:"lib/registry.ts",code:`import { OperationSpecRegistry, installOp } from '@contractspec/lib.contracts-spec';
import { CapturePayment } from './specs/billing/capture-payment';
import { handleCapturePayment } from './handlers/billing/capture-payment';

export const registry = new OperationSpecRegistry();
installOp(registry, CapturePayment, handleCapturePayment);`}),e(a,{language:"typescript",filename:"app/api/ops/[...route]/route.ts",code:`import { makeNextAppHandler } from '@contractspec/lib.contracts-runtime-server-rest/rest-next-app';
import { registry } from '@/lib/registry';
import { auth } from '@/lib/auth';

const handler = makeNextAppHandler(registry, async (req) => {
  const session = await auth(req);
  return { actor: 'user', userId: session.userId, tenantId: session.tenantId };
});

export { handler as GET, handler as POST };`})]}),t("div",{className:"card-subtle space-y-4 p-6",children:[e("h3",{className:"font-bold",children:"What you just built:"}),t("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[t("li",{children:["Type-safe API endpoint at"," ",e("code",{children:"/api/ops/billing.capturePayment"})]}),e("li",{children:"Automatic input validation (amount must be positive, IDs required)"}),e("li",{children:"Policy enforcement—only invoice owner can pay"}),e("li",{children:"Stripe integration with error handling"}),e("li",{children:"Database transaction with audit trail"}),e("li",{children:"Same spec works with GraphQL, MCP, or webhooks"})]})]}),e("div",{className:"flex items-center gap-4 pt-4",children:t(i,{href:"/docs/getting-started/dataviews",className:"btn-primary",children:["Next: Display Data with DataViews ",e(n,{size:16})]})})]})]})}export{s as HelloWorldPage};
