import { readFileSync } from 'node:fs';
import { platform, release, arch } from 'node:os';
import { execFileSync } from "node:child_process";
import {
  AuthStandardClientScopes,
  EnvironmentId,
  ORCHESTRATION_PROTOCOL_VERSION,
} from "@t3tools/contracts";
import { type RelayEnvironmentConnectResponse } from "@t3tools/contracts/relay";
import { describe, expect, it } from "@effect/vitest";
import * as Deferred from "effect/Deferred";
import * as Effect from "effect/Effect";
import * as Fiber from "effect/Fiber";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as Queue from "effect/Queue";
import * as Ref from "effect/Ref";
import * as TestClock from "effect/testing/TestClock";

import * as ManagedRelay from "../relay/managedRelay.ts";
import * as RpcHttp from "../rpc/http.ts";
import * as ClientCapabilities from "../platform/capabilities.ts";
import * as RemoteEnvironmentAuthorization from "./service.ts";
import * as TokenStore from "./tokenStore.ts";
import { BearerConnectionCredential, BearerConnectionProfile } from "../connection/catalog.ts";
import * as ConnectionCredentialStore from "../connection/credentialStore.ts";
import { BearerConnectionTarget } from "../connection/model.ts";
import * as ConnectionProfileStore from "../connection/profileStore.ts";
import * as ConnectionResolver from "../connection/resolver.ts";

const ENVIRONMENT_ID = EnvironmentId.make("environment-1");
const ENDPOINT = {
  httpBaseUrl: "https://environment.example.test",
  wsBaseUrl: "wss://environment.example.test",
  providerKind: "cloudflare_tunnel" as const,
};
const DESCRIPTOR = {
  environmentId: ENVIRONMENT_ID,
  label: "Remote environment",
  platform: {
    os: "linux",
    arch: "x64",
  },
  serverVersion: "0.0.0-test",
  capabilities: {
    repositoryIdentity: true,
  },
};
const BOOTSTRAP: RelayEnvironmentConnectResponse = {
  environmentId: ENVIRONMENT_ID,
  endpoint: ENDPOINT,
  credential: "relay-bootstrap",
  expiresAt: "2099-01-01T00:00:00.000Z",
};

type RecordedResponse = Response | ((init: RequestInit) => Response);

function recordedFetch(handler: any) {
 const calls: Array<readonly [RequestInfo | URL, RequestInit]> = [];
 const fetchFn = ((input, init) => { calls.push([input,init??{}]); return Promise.resolve(handler(input,init??{})); }) satisfies typeof fetch;
 return {calls,fetchFn};
}

const websocketTicket = (ticket: string) =>
  Response.json({
    ticket,
    expiresAt: "2099-01-01T00:00:00.000Z",
  });

const accessToken = (token: string, scope = AuthStandardClientScopes.join(" ")) =>
  Response.json({
    access_token: token,
    issued_token_type: "urn:ietf:params:oauth:token-type:access_token",
    token_type: "DPoP",
    expires_in: 3_600,
    scope,
  });

const authInvalid = () =>
  Response.json(
    {
      _tag: "EnvironmentAuthInvalidError",
      code: "auth_invalid",
      reason: "invalid_credential",
      traceId: "trace-auth-invalid",
    },
    { status: 401 },
  );

const persistedToken = (
  input: {
    readonly environmentId?: EnvironmentId;
    readonly accessToken?: string;
    readonly expiresAtEpochMs?: number;
    readonly dpopThumbprint?: string;
  } = {},
) =>
  new TokenStore.RemoteDpopAccessToken({
    environmentId: input.environmentId ?? ENVIRONMENT_ID,
    accountId: "account-1",
    label: DESCRIPTOR.label,
    endpoint: ENDPOINT,
    accessToken: input.accessToken ?? "cached-access-token",
    expiresAtEpochMs: input.expiresAtEpochMs ?? Number.MAX_SAFE_INTEGER,
    dpopThumbprint: input.dpopThumbprint ?? "thumbprint-1",
  });

const makeHarness = Effect.fn("TestRemoteAuthorization.makeHarness")(function* (input: {
  readonly initialToken?: TokenStore.RemoteDpopAccessToken;
  readonly responses: any;
  readonly bootstrap?: RelayEnvironmentConnectResponse;
  readonly beforeBootstrap?: Effect.Effect<void, ManagedRelay.ManagedRelayClientError>;
  readonly beforePut?: Effect.Effect<void>;
  readonly clerkToken?: ClientCapabilities.CloudSession["Service"]["clerkToken"];
}) {
  const tokens = yield* Ref.make(
    new Map(
      input.initialToken === undefined
        ? []
        : [[input.initialToken.environmentId, input.initialToken]],
    ),
  );
  const bootstrapCalls = yield* Ref.make(0);
  const relayInputs = yield* Ref.make<
    ReadonlyArray<Parameters<ManagedRelay.ManagedRelayClient["Service"]["connectEnvironment"]>[0]>
  >([]);
  const session = yield* Ref.make<Option.Option<ClientCapabilities.CloudSessionIdentity>>(
    Option.some({ accountId: "account-1" }),
  );
  const thumbprint = yield* Ref.make("thumbprint-1");
  const tokenReads = yield* Queue.unbounded<EnvironmentId>();
  const proofInputs = yield* Ref.make<
    ReadonlyArray<{
      readonly method: string;
      readonly url: string;
      readonly accessToken?: string;
    }>
  >([]);
  const fetch = recordedFetch(input.responses);

  const tokenStore = TokenStore.RemoteDpopAccessTokenStore.of({
    get: (environmentId) =>
      Ref.get(tokens).pipe(
        Effect.map((current) => Option.fromUndefinedOr(current.get(environmentId))),
        Effect.tap(() => Queue.offer(tokenReads, environmentId)),
      ),
    put: (token) =>
      (input.beforePut ?? Effect.void).pipe(
        Effect.andThen(
          Ref.update(tokens, (current) => {
            const next = new Map(current);
            next.set(token.environmentId, token);
            return next;
          }),
        ),
      ),
    remove: (environmentId) =>
      Ref.update(tokens, (current) => {
        const next = new Map(current);
        next.delete(environmentId);
        return next;
      }),
  });
  const signer = ManagedRelay.ManagedRelayDpopSigner.of({
    thumbprint: Ref.get(thumbprint),
    createProof: (proofInput) =>
      Ref.update(proofInputs, (current) => [...current, proofInput]).pipe(
        Effect.as(`proof:${proofInput.url}`),
      ),
  });
  const unexpected = () => Effect.die("Unexpected relay request");
  const relay = ManagedRelay.ManagedRelayClient.of({
    relayUrl: "https://relay.example.test",
    listEnvironments: unexpected,
    listDevices: unexpected,
    createEnvironmentLinkChallenge: unexpected,
    linkEnvironment: unexpected,
    unlinkEnvironment: unexpected,
    getEnvironmentStatus: unexpected,
    connectEnvironment: (request) =>
      Effect.gen(function* () {
        yield* Ref.update(bootstrapCalls, (count) => count + 1);
        yield* Ref.update(relayInputs, (current) => [...current, request]);
        yield* input.beforeBootstrap ?? Effect.void;
        return input.bootstrap ?? BOOTSTRAP;
      }),
    registerDevice: unexpected,
    unregisterDevice: unexpected,
    registerLiveActivity: unexpected,
    getAgentActivitySnapshot: unexpected,
    resetTokenCache: Effect.void,
  });
  const layer = RemoteEnvironmentAuthorization.layer.pipe(
    Layer.provideMerge(
      Layer.mergeAll(
        RpcHttp.layerRemoteHttpClient(fetch.fetchFn),
        Layer.succeed(ManagedRelay.ManagedRelayDpopSigner, signer),
        Layer.succeed(ManagedRelay.ManagedRelayClient, relay),
        Layer.succeed(ClientCapabilities.CloudSession, {
          identity: Ref.get(session),
          clerkToken: input.clerkToken ?? Effect.succeed("clerk-session"),
        }),
        Layer.succeed(ClientCapabilities.RelayDeviceIdentity, {
          deviceId: Effect.succeedSome("device-1"),
        }),
        Layer.succeed(TokenStore.RemoteDpopAccessTokenStore, tokenStore),
        Layer.succeed(
          ClientCapabilities.ClientPresentation,
          ClientCapabilities.ClientPresentation.of({
            metadata: {
              label: "T3 Code Test",
              deviceType: "mobile",
              os: "test",
            },
          }),
        ),
      ),
    ),
  );
  return {
    layer,
    tokens,
    bootstrapCalls,
    proofInputs,
    fetch,
    relayInputs,
    session,
    thumbprint,
    tokenReads,
  };
});


import * as Driver from '../connection/driver.ts';
import * as RpcSession from '../rpc/session.ts';
import { PrimaryConnectionTarget, RelayConnectionTarget, SshConnectionTarget } from '../connection/model.ts';
import { SshConnectionProfile } from '../connection/catalog.ts';
console.log(JSON.stringify({environment:{node:process.version,runner:'global vp v1.3.0 / local vite-plus v1.4.0 / Vitest v5.0.5',os:`${platform()} ${release()} ${arch()}`,vm:readFileSync('/home/ubuntu/.agents/MACHINE','utf8').trim()}}));
const SHA=execFileSync('git',['rev-parse','HEAD'],{encoding:'utf8'}).trim();
if(!['5808469018fb95676af148e7a7662c23665c67a3','db41c18dc69938e7196e221cc7e79982d82e5815'].includes(SHA)) throw new Error('Evidence requires the pinned base or head revision');
const DIRECT={httpBaseUrl:'https://direct.example.test',wsBaseUrl:'wss://direct.example.test'};
const currentDescriptor={...DESCRIPTOR,capabilities:{repositoryIdentity:true,serverSelfUpdate:'respawn',serverSelfUpdateProgress:true},orchestrationProtocolVersion:ORCHESTRATION_PROTOCOL_VERSION};
const unused=()=>Effect.die('unused');
type Config={name:string,broker:'bearer'|'primary'|'ssh'|'dpop'|'none'|'relay',token?:'cold'|'expired'|'rejected',variant?:string,protocol?:number|null,update?:boolean,driver?:boolean};
const configs:Config[] = [
 {name:'driver-preflight-connect',broker:'bearer',driver:true},
 {name:'driver-direct-ticket-transient-to-relay',broker:'dpop',variant:'alternate-transient',driver:true},
 {name:'driver-direct-mismatch-to-relay',broker:'dpop',variant:'alternate-mismatch',driver:true},
 {name:'driver-direct-unavailable-to-relay',broker:'dpop',variant:'alternate-unavailable',driver:true},
 {name:'relay-fallback-unsupported',broker:'relay',protocol:0},
 {name:'relay-fallback-update-unsupported',broker:'relay',protocol:0,update:true},
 {name:'relay-fallback-wrong-identity',broker:'relay',variant:'identity-always'},
 ...(['bearer','primary','ssh','dpop'] as const).map(broker=>({name:`${broker}-cold-warm-expiredTTL`,broker})),
 ...(['bearer','dpop'] as const).flatMap(broker=>['identity-swap','descriptor-fail','ticket-reject','metadata-swap'].map(variant=>({name:`${broker}-${variant}`,broker,variant}))),
 ...(['dpop'] as const).flatMap(broker=>(['cold','expired','rejected'] as const).map(token=>({name:`${broker}-token-${token}`,broker,token}))),
 ...([null,ORCHESTRATION_PROTOCOL_VERSION-1,ORCHESTRATION_PROTOCOL_VERSION+1] as const).flatMap(protocol=>[false,true].map(update=>({name:`bearer-protocol-${protocol}-${update?'update':'prepare'}`,broker:'bearer' as const,protocol,update}))),
 {name:'metadata-swap-update',broker:'bearer',variant:'metadata-swap',update:true},
 {name:'primary-no-bearer',broker:'none'},
 {name:'relay-cached',broker:'relay'},
 ...(['cold','expired','rejected'] as const).map(token=>({name:`relay-${token}`,broker:'relay' as const,token})),
 {name:'relay-transient',broker:'relay',variant:'ticket-transient'},
 {name:'fallback-wrong-identity',broker:'none',variant:'identity-always'},
 {name:'fallback-unsupported',broker:'none',protocol:0},
 {name:'fallback-update-unsupported',broker:'none',protocol:0,update:true},
 {name:'direct-transient-then-relay',broker:'dpop',variant:'alternate-transient'},
 {name:'direct-mismatch-then-relay',broker:'dpop',variant:'alternate-mismatch'},
];
for (const config of configs) it.live(`${config.driver||config.broker==='none'||config.broker==='relay'||config.variant?.startsWith('alternate')?'R3':'R2'} ${config.name}`,()=>Effect.gen(function*(){
 for(let sample=1;sample<=3;sample++) {
  let attempt=0,ticketCount=0;let trafficContext='prepare';let prepareAttempt=0; const requests:any[]=[]; const phases:any[]=[];
  let descriptor:any={...currentDescriptor,...(config.protocol===undefined?{}:{orchestrationProtocolVersion:config.protocol===null?undefined:config.protocol})};
  let releaseTicket:()=>void=()=>{};
  let ticketHeldResolve:()=>void=()=>{};
  const ticketHeld=new Promise<void>(resolve=>ticketHeldResolve=resolve);
  const gate=new Promise<void>(resolve=>releaseTicket=resolve);
  const handler=async(input:any,init:RequestInit)=>{
    const url=new URL(String(input)); const headers=new Headers(init.headers);
    const auth=headers.get('authorization')?.split(' ')[0]??'none';
    const req:any={index:requests.length+1,method:init.method??'GET',origin:url.origin,path:url.pathname,authorizationKind:auth,trafficContext,prepareAttempt};
    requests.push(req);
    if(url.pathname==='/.well-known/t3/environment') {
      if(config.variant==='descriptor-fail'||(config.variant==='alternate-unavailable'&&url.origin===DIRECT.httpBaseUrl)) {req.response=503; return Response.json({error:'unavailable'},{status:503});}
      const wrong=config.variant==='identity-always'||(config.variant==='identity-swap'&&attempt>0)||(config.variant==='alternate-mismatch'&&url.origin===DIRECT.httpBaseUrl);
      const body={...descriptor,...(wrong?{environmentId:'wrong-environment'}:{})};
      req.descriptor=body; return Response.json(body);
    }
    if(url.pathname==='/oauth/token') {req.response='synthetic-token-exchange';return accessToken('fresh-access-token');}
    if(url.pathname==='/api/auth/websocket-ticket/rpc') {
      ticketCount++;req.ticketOrdinal=ticketCount;req.ticketExpiresAt='2099-01-01T00:00:00.000Z';
      if(config.variant==='metadata-swap') {phases.push('ticket-held');ticketHeldResolve();await gate;phases.push('ticket-released');}
      if(config.variant==='ticket-reject'||(config.token==='rejected'&&ticketCount===1)){req.response=401;return authInvalid();}
      if((config.variant==='ticket-transient'&&ticketCount===1)||(config.variant==='alternate-transient'&&url.origin===DIRECT.httpBaseUrl)){req.response=503;return Response.json({error:'unavailable'},{status:503});}
      return websocketTicket(`ticket-${ticketCount}`);
    }
    throw new Error(`unexpected ${url.pathname}`);
  };
  const harness=yield* makeHarness({responses:handler,beforeBootstrap:Effect.sync(()=>phases.push({phase:'mock-relay-bootstrap',method:'POST',origin:'https://relay.example.test',path:`/v1/environments/${ENVIRONMENT_ID}/connect`,authorizationKind:'DPoP',observedAtHttpRequestCount:requests.length,transport:'mocked ManagedRelayClient.connectEnvironment; not included in observed HTTP count'})), ...(config.token==='cold'?{}:{initialToken:persistedToken({expiresAtEpochMs:config.token==='expired'?0:Number.MAX_SAFE_INTEGER})})});
  let profile:any=Option.none(); let target:any;
  const base={environmentId:ENVIRONMENT_ID,label:DESCRIPTOR.label};
  if(config.broker==='primary'||config.broker==='none') target=new PrimaryConnectionTarget({...base,...DIRECT});
  else if(config.broker==='relay') target=new RelayConnectionTarget(base);
  else if(config.broker==='ssh') {
   target=new SshConnectionTarget({...base,connectionId:'ssh-1'});
   profile=Option.some(new SshConnectionProfile({...base,connectionId:'ssh-1',target:{alias:'synthetic',hostname:'synthetic.example.test',username:'synthetic',port:22}}));
  } else {
   target=new BearerConnectionTarget({...base,connectionId:'direct-1'});
   profile=Option.some(new BearerConnectionProfile({...base,connectionId:'direct-1',...DIRECT,...(config.broker==='dpop'?{authorization:'t3-connect'}:{})}));
  }
  const layer=ConnectionResolver.layer.pipe(Layer.provide(Layer.mergeAll(harness.layer,
   Layer.succeed(ConnectionProfileStore.ConnectionProfileStore,{get:unused,put:()=>Effect.void,remove:unused}),
   Layer.succeed(ConnectionCredentialStore.ConnectionCredentialStore,{get:()=>Effect.succeedSome(new BearerConnectionCredential({token:'synthetic-bearer'})),put:()=>Effect.void,remove:unused}),
   Layer.succeed(ClientCapabilities.PrimaryEnvironmentAuth,{bearerToken:config.broker==='primary'?Effect.succeedSome('synthetic-bearer'):Effect.succeedNone}),
   Layer.succeed(ClientCapabilities.SshEnvironmentGateway,{provision:unused,disconnect:unused,prepare:(input:any)=>Effect.sync(()=>{phases.push('ssh-gateway-prepare');return {bootstrap:{target:input.target,...DIRECT,pairingToken:null},bearerToken:'synthetic-bearer'};})})
  )));
  yield* Effect.gen(function*(){
   const resolver=yield* ConnectionResolver.ConnectionResolver;
   const entry={target,profile,enabled:true};
   if(config.driver){
    const routeEntry:any={...entry,...(config.broker==='dpop'?{alternateRoutes:[{target:new RelayConnectionTarget(base),profile:Option.none()}]}:{})};
    const progress:any[]=[];const readyGate=yield* Deferred.make<void>();const synchronizing=yield* Deferred.make<void>();
    const observedResolver={...resolver,prepare:(input:any)=>Effect.gen(function*(){
      const id=++prepareAttempt;const route=input.target._tag;trafficContext=`resolver.prepare:${id}:${route}`;phases.push({phase:'prepare-start',attempt:id,route});
      const result=yield* resolver.prepare(input).pipe(Effect.result);phases.push({phase:'prepare-end',attempt:id,route,result:result._tag});trafficContext='route-probe';
      return result._tag==='Success'?result.success:yield* Effect.fail(result.failure);
    })};
    const driver=yield* Driver.make.pipe(
     Effect.provideService(ConnectionResolver.ConnectionResolver,observedResolver),
     Effect.provideService(RpcSession.RpcSessionFactory,{connect:(prepared:any)=>Effect.sync(()=>{phases.push({phase:'fake-session-open',route:prepared.target._tag});return {client:{},initialConfig:Effect.succeed({}),subscribeServerConfig:unused,ready:Deferred.await(readyGate),probe:Effect.void,inboundFrames:Effect.succeed(0),closed:Effect.never} as any;})}),
     Effect.provide(RpcHttp.layerRemoteHttpClient(harness.fetch.fetchFn))
    );
    const started=performance.now();
    trafficContext='preflight-route-probe';const preflight=yield* driver.preflight(routeEntry,{target,profile});
    const preflightEnd=requests.length;phases.push({phase:'preflight-result',result:preflight});
    trafficContext='connect-route-probe';
    const connecting=yield* driver.connect(routeEntry,(value:any)=>Effect.gen(function*(){progress.push({stage:value.stage,route:value.prepared?.target._tag});if(value.stage==='synchronizing')yield* Deferred.succeed(synchronizing,undefined);})).pipe(Effect.result,Effect.forkChild);
    yield* Deferred.await(synchronizing);phases.push({phase:'synchronizing-held'});yield* Deferred.succeed(readyGate,undefined);phases.push({phase:'session-ready-released'});
    const result=yield* Fiber.join(connecting);
    console.log(JSON.stringify({row:'R3',sha:SHA,fixture:config.name,sample,inputs:{entry:target._tag,alternateRoute:config.broker==='dpop'?'RelayConnectionTarget':null,variant:config.variant??null},requests,httpRequestCount:requests.length,preflightHttpRequests:preflightEnd,connectHttpRequests:requests.length-preflightEnd,prepareAttempts:prepareAttempt,preflight,progress,phaseOrder:phases,bootstrapCalls:yield* Ref.get(harness.bootstrapCalls),tokenStillCached:(yield* Ref.get(harness.tokens)).has(ENVIRONMENT_ID),result:result._tag==='Success'?{tag:'Success',route:result.success.prepared.target._tag}:{tag:result.failure._tag,reason:result.failure.reason},elapsedMs:performance.now()-started,scope:'real ConnectionDriver/preflight/connectOverRoutes + real resolver + real authorization; fake HTTP and RPC session/ready gate; route probes included separately from prepare attempts'}));
    return;
   }

   const regular=config.name.includes('cold-warm-expiredTTL');
   const attempts=regular?['cold','warm-under-10s','after-old-TTL']:config.variant==='identity-swap'?['cold','warm-identity-swap']:['single'];
   for(const phase of attempts){
    if(phase==='after-old-TTL') yield* TestClock.adjust('11 seconds');
    const offset=requests.length,bootstrapBefore=yield* Ref.get(harness.bootstrapCalls);
    const started=performance.now();
    const preparation=config.update?resolver.prepareForUpdate(entry):resolver.prepare(entry);
    let result:any;
    if(config.variant==='metadata-swap') {
      const fiber=yield* preparation.pipe(Effect.result,Effect.forkChild);
      yield* Effect.promise(()=>ticketHeld);
      descriptor={...currentDescriptor,serverVersion:'changed-during-ticket',orchestrationProtocolVersion:ORCHESTRATION_PROTOCOL_VERSION+1,capabilities:{repositoryIdentity:false,serverSelfUpdate:'boot-service',serverSelfUpdateProgress:false}};
      phases.push('descriptor-mutated-while-ticket-held');releaseTicket();
      result=yield* Fiber.join(fiber);
    } else result=yield* preparation.pipe(Effect.result);
    const summary=result._tag==='Failure'?{tag:result.failure._tag,reason:result.failure.reason,detail:result.failure.detail}: {tag:'Success',authorizationKind:(config.update?result.success.prepared:result.success).httpAuthorization?._tag??'none',ticketOrdinal:ticketCount,...(config.update?{observedDescriptor:result.success.descriptor}:{})};
    console.log(JSON.stringify({row:config.driver||config.broker==='none'||config.broker==='relay'||config.variant?.startsWith('alternate')?'R3':'R2',sha:SHA,fixture:config.name,sample,phase,broker:config.broker,inputs:{token:config.token??'cached-valid',protocol:config.protocol===null?'missing':config.protocol??'current',method:config.update?'prepareForUpdate':'prepare',variant:config.variant??null},requests:requests.slice(offset),httpRequestCount:requests.length-offset,directHttpRequests:requests.slice(offset).filter(r=>r.origin===DIRECT.httpBaseUrl).length,bootstrapCalls:(yield* Ref.get(harness.bootstrapCalls))-bootstrapBefore,phaseOrder:[...phases],elapsedMs:performance.now()-started,result:summary,tokenStillCached:(yield* Ref.get(harness.tokens)).has(ENVIRONMENT_ID)}));
    attempt++;
    if(config.variant?.startsWith('alternate')){
      const start=requests.length;
      const alternate=yield* resolver.prepare({target:new RelayConnectionTarget(base),profile:Option.none(),enabled:true}).pipe(Effect.result);
      console.log(JSON.stringify({row:'R3',sha:SHA,fixture:config.name,sample,phase:'explicit-relay-alternate-prepare',requests:requests.slice(start),bootstrapCalls:yield* Ref.get(harness.bootstrapCalls),result:alternate._tag==='Success'?'Success':{tag:alternate.failure._tag,reason:alternate.failure.reason},tokenStillCached:(yield* Ref.get(harness.tokens)).has(ENVIRONMENT_ID),scope:'resolver alternate preparation only; ConnectionDriver/connectOverRoutes not exercised'}));
    }
   }
  }).pipe(Effect.provide(layer),Effect.provide(TestClock.layer()));
 }
}).pipe(Effect.scoped));
