import { mkdtempSync, writeFileSync, existsSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { ListingsService } from '../app/modules/listings/service.mjs';
import { InventoryService } from '../app/modules/inventory/service.mjs';
import { MediaService } from '../app/modules/media/service.mjs';

const failures=[]; const assert=(c,m)=>{if(!c)failures.push(m)}; const expectThrow=(fn,code,m)=>{try{fn();failures.push(m)}catch(e){if(code&&e.code!==code)failures.push(`${m} (${e.code||e.message})`)}};
let listings=[{id:1,title:'Aktiv',deleted_at:null,tags:[],photos:[]},{id:2,title:'Papierkorb',deleted_at:'2026-01-01',tags:[],photos:[]}];
const listRepo={
 create(data){const row={id:3,...data,tags:data.tags||[],photos:data.photos||[]};listings.push(row);return row;},
 get(id){return listings.find(x=>x.id===Number(id))||null;}, list(){return listings.filter(x=>!x.deleted_at);},
 update(id,data){const row=this.get(id);Object.assign(row,data);return row;}, softDelete(id){this.get(id).deleted_at='now';},
 restore(id){this.get(id).deleted_at=null;}, listDeleted(){return listings.filter(x=>x.deleted_at);},
 permanentDelete(id){listings=listings.filter(x=>x.id!==Number(id));}, trashCount(){return this.listDeleted().length;},
 duplicate(id){const row=this.get(id);return row?this.create({...row,id:undefined,title:`${row.title} (Kopie)`,deleted_at:null}):null;},
};
const ls=new ListingsService(listRepo);
expectThrow(()=>ls.validateCreate({platform:'ebay'}),'LISTING_INPUT_INVALID','Titelpflicht wurde nicht erzwungen');
expectThrow(()=>ls.validateCreate({title:'OK',hacker:true}),'LISTING_INPUT_INVALID','Unbekanntes Listingfeld wurde akzeptiert');
const cleaned=ls.validateCreate({title:'Test',description_html:'<script>alert(1)</script><p>Text</p>',tags:['a','b']});
assert(!cleaned.description_html.includes('<script'),'HTML-Sanitizer ließ Script durch');
expectThrow(()=>ls.permanentDelete(1),'LISTING_TRASH_NOT_FOUND','Aktiver Artikel konnte endgültig gelöscht werden');
assert(ls.permanentDelete(2).ok && !listRepo.get(2),'Papierkorbartikel wurde nicht endgültig gelöscht');

const inv=new InventoryService({locations(){return[]},unassigned(){return[]},byLocation(){return[]},bulkUpdateLocation(ids){return ids.length}});
expectThrow(()=>inv.validateBulk({ids:[1],location:'A',extra:true}),'INVENTORY_INPUT_INVALID','Unbekanntes Lagerfeld wurde akzeptiert');
expectThrow(()=>inv.validateBulk({ids:Array.from({length:501},(_,i)=>i+1),location:'A'}),'INVENTORY_BATCH_TOO_LARGE','Bulk-Limit wurde nicht erzwungen');
assert(inv.bulk({ids:[1,1,2],location:'Regal A'}).updated===2,'IDs wurden nicht dedupliziert');

const dir=mkdtempSync(join(tmpdir(),'vendoo-media-'));
try{
 writeFileSync(join(dir,'free.jpg'),'x'); writeFileSync(join(dir,'used.jpg'),'x');
 const removed=[];
 const mediaRepo={list(){return[]},setFavorite(p,f){return{ok:true,image_path:p,favorite:f}},referenced(){return new Set(['used.jpg'])},removeRecords(paths){removed.push(...paths)}};
 const media=new MediaService({uploadRoot:dir,sharp:null,repository:mediaRepo});
 expectThrow(()=>media.validateDelete({image_paths:['../secret']}),'MEDIA_PATH_INVALID','Traversal-Pfad wurde akzeptiert');
 expectThrow(()=>media.validateDelete({image_paths:['free.jpg'],extra:true}),null,'Unbekanntes Medienfeld wurde akzeptiert');
 const result=media.delete({image_paths:['free.jpg','used.jpg']});
 assert(result.deleted===1 && result.protected.includes('used.jpg'),'Referenzschutz liefert falsches Ergebnis');
 assert(!existsSync(join(dir,'free.jpg')) && existsSync(join(dir,'used.jpg')),'Referenzschutz löschte falsche Datei');
 assert(removed.length===1 && removed[0]==='free.jpg','Medienrecords wurden falsch bereinigt');
} finally { rmSync(dir,{recursive:true,force:true}); }

if(failures.length){console.error(`Catalog-Service-Regression 1.39.0 fehlgeschlagen (${failures.length}):`);failures.forEach(x=>console.error(`- ${x}`));process.exit(1)}
console.log('Catalog-Service-Regression 1.39.0 erfolgreich: Listing-Allowlist, HTML-Sanitizing, Papierkorbgrenze, Inventory-Bulk-Limit, Pfadschutz und Medienreferenzen geprüft.');
