import {withMarketPreview} from './market-preview';
import {applicationOrigin} from './application-origin';
import { defaultContent, previewProjects, type Catalog, type Project, type SiteContent } from './catalog';
const withoutWallexSamples=(projects:Project[])=>projects.filter(p=>p.status==='published'&&!(p.is_demo&&['digital-oil','planck-gold','digital-copper','digital-silver','tether'].includes(p.slug)));
export function env(name:string){return process.env[name]||''}
export function configured(){return Boolean(env('SUPABASE_URL')&&env('SUPABASE_PUBLISHABLE_KEY'))}
export async function db(path:string, init:RequestInit={},token?:string){
 const url=env('SUPABASE_URL');const key=env('SUPABASE_PUBLISHABLE_KEY');if(!url||!key)throw new Error('not_configured');
 return fetch(`${url.replace(/\/$/,'')}/rest/v1/${path}`,{...init,cache:'no-store',headers:{apikey:key,...(token?{Authorization:`Bearer ${token}`} : {}),'Content-Type':'application/json',...init.headers},signal:init.signal??AbortSignal.timeout(10000)});
}
// Only public, idempotent catalog reads are retried; writes/authentication are not affected.
async function catalogRows(path:string):Promise<unknown[]|null>{
 for(let attempt=0;attempt<2;attempt++){
  try{
   const response=await db(path);
   if(!response.ok){
    if(attempt===0&&(response.status===408||response.status===429||response.status>=500))continue;
    return null;
   }
   const rows:unknown=await response.json();
   return Array.isArray(rows)?rows:null;
  }catch{if(attempt===1)return null;}
 }
 return null;
}
export async function getCatalog({designPreview=false}:{designPreview?:boolean}={}):Promise<Catalog>{
 if(designPreview&&process.env.NODE_ENV==='development')return {projects:withoutWallexSamples(withMarketPreview(previewProjects)),content:defaultContent,mode:'preview'};
 if(!configured())return env('PLANCK_PREVIEW')==='true'&&process.env.NODE_ENV!=='production'?{projects:withoutWallexSamples(withMarketPreview(previewProjects)),content:defaultContent,mode:'preview'}:{projects:[],content:defaultContent,mode:'unavailable'};
 const [projects,content]=await Promise.all([
  catalogRows('projects?status=eq.published&select=*&order=sort_order.asc'),
  catalogRows('site_content?key=eq.site&select=data'),
 ]);
 // Missing CMS content must not hide successfully read projects or break their detail pages.
 if(!projects||projects.some(row=>!row||typeof row!=='object'||Array.isArray(row)))return {projects:[],content:defaultContent,mode:'unavailable'};
 return {projects:withoutWallexSamples(projects as Project[]),content:(content as {data:SiteContent}[]|null)?.[0]?.data||defaultContent,mode:'live'};
}
export function json(body:unknown,status=200){return Response.json(body,{status,headers:{'Cache-Control':'no-store','X-Content-Type-Options':'nosniff'}})}
export function sameOrigin(request:Request){try{const origin=request.headers.get('origin');return !!origin&&origin===applicationOrigin(request)}catch{return false}}
export function tokenFrom(request:Request){const match=request.headers.get('cookie')?.match(/(?:^|;\s*)planck_session=([^;]+)/);return match?.[1]||''}
export async function getUser(token:string){if(!configured()||!token)return null;try{const res=await fetch(`${env('SUPABASE_URL')}/auth/v1/user`,{headers:{apikey:env('SUPABASE_PUBLISHABLE_KEY'),Authorization:`Bearer ${token}`},signal:AbortSignal.timeout(10000)});if(!res.ok)return null;const user=await res.json() as {id:string;email:string};const {requireAccountAccess}=await import('./account-access-server');await requireAccountAccess(token,'login',user.id);return user}catch{return null}}

export async function readJson(request:Request,limit=150000):Promise<unknown>{
 const reader=request.body?.getReader();if(!reader)throw new Error('درخواست خالی است.');const chunks:Uint8Array[]=[];let size=0;
 while(true){const {done,value}=await reader.read();if(done)break;size+=value.byteLength;if(size>limit){await reader.cancel();throw new Error('اطلاعات بیش از حد مجاز است.')}chunks.push(value)}
 const data=new Uint8Array(size);let offset=0;for(const c of chunks){data.set(c,offset);offset+=c.byteLength}return JSON.parse(new TextDecoder().decode(data));
}
