import {AuthError,authRequest,assertAuthResult} from './customer-auth';
import {cookieValue,setAuthCookie,isAuthSession,type AuthSession} from './auth-cookies';
import {env,json} from './server';
import {normalizePhone} from './auth-input';

export const registrationTestCode='123456';
const cookie='planck_registration_test',lifetime=10*60*1000;
type Registration={phone:string;password:string;metadata:Record<string,unknown>};
type Pending=Registration&{expires:number;attempts:number;busy:boolean;created:boolean;resendAt:number};
const pending=new Map<string,Pending>();
let directWindowStart=0,directAttempts=0;

// This adapter is deliberately unavailable in production and on remote hosts.
export function registrationTestMode(request:Request){
 const host=new URL(request.url).hostname;
 const until=Date.parse(env('PLANCK_REGISTRATION_TEST_UNTIL'));
 return process.env.NODE_ENV==='development'&&['localhost','127.0.0.1','[::1]'].includes(host)
  &&env('PLANCK_REGISTRATION_TEST')==='true'&&env('SANDBOX_REGISTRATION_TOKEN').length>=48
  &&Number.isFinite(until)&&until>Date.now();
}
export function directRegistrationTestMode(request:Request){
 return registrationTestMode(request)&&env('PLANCK_REGISTRATION_TEST_SKIP_OTP')==='true';
}
async function createTestAccount(registration:Registration){
 const result=await fetch(`${env('SUPABASE_URL').replace(/\/$/,'')}/functions/v1/sandbox-registration`,{
  method:'POST',cache:'no-store',headers:{Authorization:`Bearer ${env('SANDBOX_REGISTRATION_TOKEN')}`,'Content-Type':'application/json'},
  body:JSON.stringify(registration),signal:AbortSignal.timeout(15000)
 });
 if(!result.ok)throw new AuthError(result.status===409?'این شماره قبلاً ثبت شده است؛ با رمز عبور وارد حساب شوید.':'ساخت حساب آزمایشی انجام نشد؛ دوباره تلاش کنید.',result.status===409?409:503);
}
export async function directTestRegistration(request:Request,registration:Registration):Promise<AuthSession>{
 if(!directRegistrationTestMode(request))throw new AuthError('ثبت‌نام بدون پیامک غیرفعال است.',403);
 const now=Date.now();
 if(now-directWindowStart>=60000||now<directWindowStart){directWindowStart=now;directAttempts=0}
 if(directAttempts>=5)throw new AuthError('تعداد تلاش‌های ثبت‌نام بیش از حد مجاز است؛ یک دقیقه بعد دوباره تلاش کنید.',429);
 directAttempts++;
 // Creation is deliberately required before login: an existing phone can never
 // be confirmed, changed or signed in through this temporary registration path.
 await createTestAccount(registration);
 const {result,data}=await authRequest('token?grant_type=password',{phone:registration.phone,password:registration.password});
 assertAuthResult(result,data,'حساب ساخته شد؛ ورود را با شماره موبایل و رمز عبور انجام دهید.');
 if(!isAuthSession(data)||!data.user.phone_confirmed_at)throw new AuthError('ورود به حساب آزمایشی کامل نشد.',503);
 const phone=normalizePhone(data.user.phone)||normalizePhone(`+${data.user.phone}`);
 if(phone!==registration.phone)throw new AuthError('ورود به حساب آزمایشی کامل نشد.',503);
 return data;
}
function clean(){for(const [key,value] of pending)if(value.expires<=Date.now())pending.delete(key)}
export function beginTestRegistration(request:Request,registration:Registration){
 clean();
 const old=cookieValue(request,cookie);if(old)pending.delete(old);
 if(pending.size>=100)throw new AuthError('ظرفیت ثبت‌نام آزمایشی تکمیل است؛ چند دقیقه بعد دوباره تلاش کنید.',429);
 const challenge=crypto.randomUUID();
 pending.set(challenge,{...registration,expires:Date.now()+lifetime,attempts:0,busy:false,created:false,resendAt:Date.now()+60000});
 const response=json({phone:registration.phone,step:'verify',verificationMode:'sandbox',testCode:registrationTestCode});
 setAuthCookie(response,request,cookie,challenge,lifetime/1000,'/api/auth');return response;
}
export function hasTestRegistration(request:Request){return !!cookieValue(request,cookie)}
export async function verifyTestRegistration(request:Request,phone:string,code:string):Promise<AuthSession>{
 if(!registrationTestMode(request))throw new AuthError('ثبت‌نام آزمایشی غیرفعال است.',403);
 clean();const id=cookieValue(request,cookie),entry=pending.get(id);
 if(!entry||entry.phone!==phone)throw new AuthError('زمان ثبت‌نام آزمایشی تمام شده است؛ دوباره فرم ثبت‌نام را تکمیل کنید.',400);
 if(entry.busy)throw new AuthError('ثبت‌نام در حال انجام است.',409);
 if(entry.attempts>=5){pending.delete(id);throw new AuthError('تعداد تلاش‌ها بیش از حد مجاز است؛ ثبت‌نام را دوباره شروع کنید.',429)}
 entry.attempts++;
 if(code!==registrationTestCode)throw new AuthError('کد آزمایشی را وارد کنید: ۱۲۳۴۵۶.');
 entry.busy=true;
 try{
  if(!entry.created){
   await createTestAccount({phone:entry.phone,password:entry.password,metadata:entry.metadata});
   entry.created=true;
  }
  const {result,data}=await authRequest('token?grant_type=password',{phone:entry.phone,password:entry.password});
  assertAuthResult(result,data,'حساب ساخته شد؛ ورود را با شماره موبایل و رمز عبور انجام دهید.');
  if(!isAuthSession(data))throw new AuthError('ورود به حساب آزمایشی کامل نشد.',503);
  pending.delete(id);return data;
 }finally{entry.busy=false}
}
export function resendTestRegistration(request:Request,phone:string){
 if(!registrationTestMode(request))throw new AuthError('ثبت‌نام آزمایشی غیرفعال است.',403);
 clean();const entry=pending.get(cookieValue(request,cookie));
 if(!entry||entry.phone!==phone)throw new AuthError('فرم ثبت‌نام را دوباره تکمیل کنید.');
 if(entry.resendAt>Date.now())throw new AuthError('برای درخواست مجدد کد کمی صبر کنید.',429);
 entry.resendAt=Date.now()+60000;
 return json({phone,step:'verify',verificationMode:'sandbox',testCode:registrationTestCode});
}
export function clearTestRegistration(response:Response,request:Request){setAuthCookie(response,request,cookie,'',0,'/api/auth')}
