export const storefrontThemes=['mint','violet','amber'] as const;
export type StorefrontTheme=typeof storefrontThemes[number];
export type StorefrontConfig={name:string;intro:string;assets:string[];theme:StorefrontTheme};
export type StorefrontError='name'|'intro'|'assets'|'theme';
type Query=Record<string,string|string[]|undefined>;
type ParsedStorefront={config:StorefrontConfig;error:null}|{config:null;error:StorefrontError};
// eslint-disable-next-line no-control-regex -- Reject hidden controls and bidi overrides in public storefront labels.
const controls=/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/;
const assetId=/^[a-zA-Z0-9][a-zA-Z0-9:_-]{0,95}$/;

/** A storefront is a public, bounded URL configuration, never a saved account resource. */
export function parseStorefrontConfig(query:Query):ParsedStorefront {
 const clean=(value:unknown,max:number):string|null=>{
  if(typeof value!=='string'||value.length>max*4||controls.test(value))return null;
  const normalized=value.normalize('NFC').replace(/\s+/gu,' ').trim();
  return normalized.length<=max?normalized:null;
 };
 const name=clean(query.name,60);
 if(!name)return {config:null,error:'name'};
 const intro=query.intro===undefined?'':clean(query.intro,160);
 if(intro===null)return {config:null,error:'intro'};
 if(typeof query.assets!=='string'||query.assets.length>12*97)return {config:null,error:'assets'};
 const ids=query.assets.split(',');
 if(ids.length<1||ids.length>12||ids.some(id=>!assetId.test(id)))return {config:null,error:'assets'};
 const theme=query.theme===undefined?'mint':query.theme;
 if(typeof theme!=='string'||!storefrontThemes.includes(theme as StorefrontTheme))return {config:null,error:'theme'};
 return {config:{name,intro,assets:[...new Set(ids)],theme:theme as StorefrontTheme},error:null};
}

export function buildStorefrontPath(input:StorefrontConfig):string|null {
 const result=parseStorefrontConfig({name:input.name,intro:input.intro,assets:input.assets.join(','),theme:input.theme});
 if(!result.config)return null;
 const config=result.config;
 const query=new URLSearchParams({name:config.name,...(config.intro?{intro:config.intro}:{}),assets:config.assets.join(','),theme:config.theme});
 return `/storefront?${query.toString()}`;
}

/** Re-resolve IDs against the current public catalog; never trust asset details from a URL. */
export function resolveStorefrontAssets<T extends {id:string;status?:string;kind?:string}>(ids:readonly string[],catalog:readonly T[]):{assets:T[];missing:string[]} {
 const available=new Map(catalog.filter(asset=>asset.status==='published'||asset.kind==='wallex').map(asset=>[asset.id,asset]));
 const assets:T[]=[],missing:string[]=[];
 for(const id of new Set(ids)){
  const asset=available.get(id);
  if(asset)assets.push(asset);else missing.push(id);
 }
 return {assets,missing};
}
