import assert from 'node:assert/strict';
import { createHash, randomUUID } from 'node:crypto';
import test, { after } from 'node:test';
import { and, eq, inArray } from 'drizzle-orm';
import {
  accounts,
  activities,
  allocations,
  capacityCommitments,
  createDatabase,
  demandDeals,
  invites,
  teamMemberships,
  users,
} from '@pig/db';
import { createApp } from '../src/app';
import { loadConfig } from '../src/lib/config';

const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) throw new Error('DATABASE_URL is required for the critical-path E2E test.');

const db = createDatabase({ url: databaseUrl, max: 4 });

after(async () => {
  await db.$client.end();
});

test('invite-bound member creates, sells and observes capacity through authenticated HTTP', async () => {
  const suffix = randomUUID();
  const email = `e2e-${suffix}@example.test`;
  const subject = randomUUID();
  const accessToken = `e2e-token-${suffix}`;
  const inviteCode = `invite-${suffix}`;
  const startsAt = new Date('2027-01-01T00:00:00.000Z');
  const endsAt = new Date('2027-01-01T10:00:00.000Z');
  let inviteId: string | undefined;
  let userId: string | undefined;
  let supplyAccountId: string | undefined;
  let demandAccountId: string | undefined;
  let demandDealId: string | undefined;
  let commitmentId: string | undefined;
  let allocationId: string | undefined;

  const config = loadConfig({
    ...process.env,
    NODE_ENV: 'production',
    DATABASE_URL: databaseUrl,
    PIG_PUBLIC_URL: 'https://pig-e2e.invalid',
    SUPABASE_URL: 'https://identity-e2e.invalid',
    SUPABASE_ANON_KEY: 'e2e-anon-key',
    SUPABASE_SERVICE_KEY: '',
    PIG_ADMIN_EMAILS: '',
    PIGGY_ENABLED: 'false',
  });
  const authProvider = {
    name: 'e2e-stub',
    async verifyAccessToken(token: string) {
      if (token !== accessToken) throw new Error('Invalid E2E token.');
      return { subject, email };
    },
  };
  const app = createApp(config, db, authProvider);

  try {
    const [invite] = await db
      .insert(invites)
      .values({
        codeHash: createHash('sha256').update(inviteCode).digest('hex'),
        email,
        usesRemaining: 1,
      })
      .returning();
    assert.ok(invite);
    inviteId = invite.id;

    // A valid external identity is authentication, not workspace membership.
    const ungatedSignup = await request(app, '/api/signup', {
      token: accessToken,
      body: { name: 'E2E Capacity Seller', team: 'supply' },
    });
    assert.equal(ungatedSignup.status, 403);
    assert.equal(ungatedSignup.body.code, 'invite_required');
    const uninvitedUsers = await db.select().from(users).where(eq(users.email, email));
    assert.equal(uninvitedUsers.length, 0);

    // The password registration route also stays closed without its provider
    // administration credential; the injected verifier is not a bypass.
    const openRegistration = await request(app, '/api/register', {
      body: {
        email,
        password: 'not-a-production-password',
        name: 'E2E Capacity Seller',
        team: 'supply',
        inviteCode,
      },
    });
    assert.equal(openRegistration.status, 503);
    assert.equal(openRegistration.body.code, 'registration_unavailable');

    const signup = await request(app, '/api/signup', {
      token: accessToken,
      body: {
        name: 'E2E Capacity Seller',
        team: 'supply',
        title: 'Capacity lead',
        inviteCode,
      },
    });
    assert.equal(signup.status, 201);
    const signupUser = record(signup.body.user, 'signup user');
    userId = text(signupUser.id, 'signup user id');
    assert.equal(signupUser.email, email);
    assert.equal(signupUser.isPlatformAdmin, false);

    const [consumedInvite] = await db
      .select()
      .from(invites)
      .where(eq(invites.id, inviteId));
    assert.ok(consumedInvite);
    assert.equal(consumedInvite.usesRemaining, 0);
    assert.equal(consumedInvite.redeemedByUserId, userId);

    // Fixture setup grants only the two capabilities this path needs. Product
    // writes below still pass through the real authorization middleware.
    await db
      .update(teamMemberships)
      .set({ role: 'lead' })
      .where(
        and(
          eq(teamMemberships.userId, userId),
          eq(teamMemberships.team, 'supply'),
        ),
      );
    await db.insert(teamMemberships).values({
      userId,
      team: 'demand',
      role: 'member',
      isPrimary: false,
    });

    const me = await request(app, '/api/me', { token: accessToken, method: 'GET' });
    assert.equal(me.status, 200);
    assert.equal(me.body.id, userId);
    assert.equal(me.body.via, 'jwt');
    const grants = array(me.body.permissions, 'permissions');
    assert.ok(
      grants.some(
        (grant) =>
          record(grant, 'permission').capability === 'commitment:write' &&
          record(grant, 'permission').team === 'supply',
      ),
    );
    assert.ok(
      grants.some(
        (grant) =>
          record(grant, 'permission').capability === 'deal:write' &&
          record(grant, 'permission').team === 'demand',
      ),
    );

    const [supplyAccount, demandAccount] = await Promise.all([
      db
        .insert(accounts)
        .values({ name: `E2E Supply ${suffix}`, side: 'supply' })
        .returning()
        .then(([row]) => row),
      db
        .insert(accounts)
        .values({ name: `E2E Demand ${suffix}`, side: 'demand' })
        .returning()
        .then(([row]) => row),
    ]);
    assert.ok(supplyAccount);
    assert.ok(demandAccount);
    supplyAccountId = supplyAccount.id;
    demandAccountId = demandAccount.id;

    const [deal] = await db
      .insert(demandDeals)
      .values({
        accountId: demandAccount.id,
        name: `E2E Reserved Cluster ${suffix}`,
        stage: 'deployment',
        productLine: 'compute_reserved',
        ownerUserId: userId,
      })
      .returning();
    assert.ok(deal);
    demandDealId = deal.id;

    const baselineMarginResponse = await request(app, '/api/capacity/margin', {
      token: accessToken,
      method: 'GET',
    });
    assert.equal(baselineMarginResponse.status, 200);
    const baselineMargin = marginTotals(baselineMarginResponse.body);

    const commitmentResponse = await request(app, '/api/commitments', {
      token: accessToken,
      body: {
        accountId: supplyAccount.id,
        name: `E2E Eight-GPU Block ${suffix}`,
        gpuType: 'H100_80GB',
        gpuCount: 8,
        interconnectType: 'Unknown',
        securityTier: 'secure_cloud',
        startsAt: startsAt.toISOString(),
        endsAt: endsAt.toISOString(),
        totalGpuHours: 80,
        costPerGpuHourCents: 100,
      },
    });
    assert.equal(commitmentResponse.status, 200);
    commitmentId = text(commitmentResponse.body.id, 'commitment id');

    const availabilityBefore = await request(app, '/api/capacity/availability', {
      token: accessToken,
      method: 'GET',
    });
    assert.equal(availabilityBefore.status, 200);
    const capacityBefore = findById(
      array(availabilityBefore.body, 'availability'),
      'commitmentId',
      commitmentId,
    );
    assert.equal(capacityBefore.totalGpuHours, 80);
    assert.equal(capacityBefore.soldGpuHours, 0);
    assert.equal(capacityBefore.availableGpuHours, 80);

    const marginBeforeResponse = await request(app, '/api/capacity/margin', {
      token: accessToken,
      method: 'GET',
    });
    assert.equal(marginBeforeResponse.status, 200);
    const marginBefore = marginTotals(marginBeforeResponse.body);
    assert.equal(marginBefore.revenueCents - baselineMargin.revenueCents, 0);
    assert.equal(marginBefore.costCents - baselineMargin.costCents, 8_000);
    assert.equal(marginBefore.grossMarginCents - baselineMargin.grossMarginCents, -8_000);

    const allocationResponse = await request(app, '/api/allocations', {
      token: accessToken,
      body: {
        capacityCommitmentId: commitmentId,
        demandDealId: deal.id,
        gpuHours: 40,
        pricePerGpuHourCents: 300,
        startsAt: startsAt.toISOString(),
        endsAt: endsAt.toISOString(),
        status: 'committed',
      },
    });
    assert.equal(allocationResponse.status, 200);
    allocationId = text(allocationResponse.body.id, 'allocation id');

    const availabilityAfter = await request(app, '/api/capacity/availability', {
      token: accessToken,
      method: 'GET',
    });
    const capacityAfter = findById(
      array(availabilityAfter.body, 'availability'),
      'commitmentId',
      commitmentId,
    );
    assert.equal(capacityAfter.soldGpuHours, 40);
    assert.equal(capacityAfter.heldGpuHours, 0);
    assert.equal(capacityAfter.availableGpuHours, 40);
    assert.equal(capacityAfter.utilisation, 0.5);

    const marginAfterResponse = await request(app, '/api/capacity/margin', {
      token: accessToken,
      method: 'GET',
    });
    assert.equal(marginAfterResponse.status, 200);
    const marginAfter = marginTotals(marginAfterResponse.body);
    assert.equal(marginAfter.revenueCents - marginBefore.revenueCents, 12_000);
    // The full block remains the cost basis even though only half was sold.
    assert.equal(marginAfter.costCents - marginBefore.costCents, 0);
    assert.equal(marginAfter.grossMarginCents - marginBefore.grossMarginCents, 12_000);
    assert.equal(marginAfter.grossMarginCents - baselineMargin.grossMarginCents, 4_000);
  } finally {
    if (allocationId) await db.delete(allocations).where(eq(allocations.id, allocationId));
    if (commitmentId) {
      await db.delete(capacityCommitments).where(eq(capacityCommitments.id, commitmentId));
    }
    if (demandDealId) await db.delete(demandDeals).where(eq(demandDeals.id, demandDealId));
    if (userId) await db.delete(activities).where(eq(activities.actorUserId, userId));
    const accountIds = [supplyAccountId, demandAccountId].filter(
      (id): id is string => id !== undefined,
    );
    if (accountIds.length) await db.delete(accounts).where(inArray(accounts.id, accountIds));
    if (inviteId) await db.delete(invites).where(eq(invites.id, inviteId));
    if (userId) await db.delete(users).where(eq(users.id, userId));
  }
});

async function request(
  app: ReturnType<typeof createApp>,
  path: string,
  options: { token?: string; body?: unknown; method?: 'GET' | 'POST' } = {},
): Promise<{ status: number; body: Record<string, unknown> }> {
  const response = await app.request(path, {
    method: options.method ?? 'POST',
    headers: {
      ...(options.token ? { authorization: `Bearer ${options.token}` } : {}),
      ...(options.body === undefined ? {} : { 'content-type': 'application/json' }),
    },
    ...(options.body === undefined ? {} : { body: JSON.stringify(options.body) }),
  });
  return {
    status: response.status,
    body: (await response.json()) as Record<string, unknown>,
  };
}

function record(value: unknown, label: string): Record<string, unknown> {
  assert.ok(value && typeof value === 'object' && !Array.isArray(value), `${label} must be an object`);
  return value as Record<string, unknown>;
}

function array(value: unknown, label: string): unknown[] {
  assert.ok(Array.isArray(value), `${label} must be an array`);
  return value;
}

function text(value: unknown, label: string): string {
  if (typeof value !== 'string') {
    assert.fail(`${label} must be a string`);
  }
  return value;
}

function findById(rows: unknown[], field: string, id: string): Record<string, unknown> {
  const found = rows.map((row) => record(row, 'row')).find((row) => row[field] === id);
  assert.ok(found, `Expected ${field}=${id}`);
  return found;
}

function marginTotals(body: Record<string, unknown>): {
  revenueCents: number;
  costCents: number;
  grossMarginCents: number;
} {
  const totals = record(body.totals, 'margin totals');
  return {
    revenueCents: number(totals.revenueCents, 'margin revenue'),
    costCents: number(totals.costCents, 'margin cost'),
    grossMarginCents: number(totals.grossMarginCents, 'gross margin'),
  };
}

function number(value: unknown, label: string): number {
  if (typeof value !== 'number') {
    assert.fail(`${label} must be a number`);
  }
  return value;
}
