const crypto=require("crypto"),db=require("../../models"),service=require("../../services/shipping/shipping.service"),cart=require("../../services/shopping/cart.service"),{logActivity}=require("../../services/activity.service");const audit=(req,type,id)=>logActivity({user:req.user,type,module:"Shipping",targetId:id,requestId:req.id});exports.quote=async(req,res,next)=>{try{const address=await db.Address.findOne({where:{id:req.body.addressId,user_id:req.user.id}});if(!address)throw Object.assign(new Error("Address not found"),{status:404,code:"NOT_FOUND"});const projection=await cart.project(req.user.id);res.json({success:true,data:await service.getAvailableMethods({address,subtotal:projection.merchandiseTotal,currency:projection.currency})});}catch(e){next(e);}};const list=model=>async(req,res,next)=>{try{res.json({success:true,data:await model.findAll()});}catch(e){next(e);}};exports.zones=list(db.ShippingZone);exports.methods=list(db.ShippingMethod);exports.rates=list(db.ShippingRate);exports.createZone=async(req,res,next)=>{try{let row;await db.sequelize.transaction(async t=>{row=await db.ShippingZone.create({id:crypto.randomUUID(),code:req.body.code.toUpperCase(),name:req.body.name,status:req.body.status,duty_mode:req.body.dutyMode},{transaction:t});await db.ShippingZoneRegion.bulkCreate(req.body.regions.map(x=>({id:crypto.randomUUID(),shipping_zone_id:row.id,country_code:x.countryCode.toUpperCase(),province:x.province,district:x.district})),{transaction:t});});await audit(req,"SHIPPING_ZONE_CREATED",row.id);res.status(201).json({success:true,data:row});}catch(e){next(e);}};exports.createMethod=async(req,res,next)=>{try{const b=req.body,row=await db.ShippingMethod.create({id:crypto.randomUUID(),code:b.code.toUpperCase(),name:b.name,description:b.description,status:b.status,estimated_min_days:b.estimatedMinDays,estimated_max_days:b.estimatedMaxDays,tracking_supported:b.trackingSupported});await audit(req,"SHIPPING_METHOD_CREATED",row.id);res.status(201).json({success:true,data:row});}catch(e){next(e);}};exports.createRate=async(req,res,next)=>{try{const b=req.body,row=await db.ShippingRate.create({id:crypto.randomUUID(),shipping_zone_id:b.shippingZoneId,shipping_method_id:b.shippingMethodId,currency:b.currency.toUpperCase(),base_amount:b.baseAmount,free_shipping_threshold:b.freeShippingThreshold,minimum_subtotal:b.minimumSubtotal,maximum_subtotal:b.maximumSubtotal,status:b.status,starts_at:b.startsAt,ends_at:b.endsAt});await audit(req,"SHIPPING_RATE_CREATED",row.id);res.status(201).json({success:true,data:row});}catch(e){next(e);}}; exports.updateZone=async(req,res,next)=>{try{let row;await db.sequelize.transaction(async t=>{row=await db.ShippingZone.findByPk(req.params.id,{transaction:t,lock:t.LOCK.UPDATE});if(!row)throw Object.assign(new Error("Zone not found"),{status:404,code:"NOT_FOUND"});await row.update({code:req.body.code.toUpperCase(),name:req.body.name,status:req.body.status,duty_mode:req.body.dutyMode},{transaction:t});await db.ShippingZoneRegion.destroy({where:{shipping_zone_id:row.id},transaction:t});await db.ShippingZoneRegion.bulkCreate(req.body.regions.map(x=>({id:crypto.randomUUID(),shipping_zone_id:row.id,country_code:x.countryCode.toUpperCase(),province:x.province,district:x.district})),{transaction:t});});await audit(req,"SHIPPING_ZONE_UPDATED",row.id);res.json({success:true,data:row});}catch(e){next(e);}}; exports.updateMethod=async(req,res,next)=>{try{const b=req.body,row=await db.ShippingMethod.findByPk(req.params.id);if(!row)throw Object.assign(new Error("Method not found"),{status:404,code:"NOT_FOUND"});await row.update({code:b.code.toUpperCase(),name:b.name,description:b.description,status:b.status,estimated_min_days:b.estimatedMinDays,estimated_max_days:b.estimatedMaxDays,tracking_supported:b.trackingSupported});await audit(req,"SHIPPING_METHOD_UPDATED",row.id);res.json({success:true,data:row});}catch(e){next(e);}}; exports.updateRate=async(req,res,next)=>{try{const b=req.body,row=await db.ShippingRate.findByPk(req.params.id);if(!row)throw Object.assign(new Error("Rate not found"),{status:404,code:"NOT_FOUND"});await row.update({shipping_zone_id:b.shippingZoneId,shipping_method_id:b.shippingMethodId,currency:b.currency.toUpperCase(),base_amount:b.baseAmount,free_shipping_threshold:b.freeShippingThreshold,minimum_subtotal:b.minimumSubtotal,maximum_subtotal:b.maximumSubtotal,status:b.status,starts_at:b.startsAt,ends_at:b.endsAt});await audit(req,"SHIPPING_RATE_UPDATED",row.id);res.json({success:true,data:row});}catch(e){next(e);}};