import json, re

# ── Load inquiry.html ──
with open('/tmp/inquiry.html', 'r', encoding='utf-8') as f:
    html = f.read()

# ── Load seller data ──
with open('/tmp/inquiry_seller_data.json', 'r', encoding='utf-8') as f:
    seller_data_raw = f.read()

# ── 1. Add D3.js in <head> ──
D3_TAG = '<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>\n'
if 'd3.min.js' not in html:
    html = html.replace('</head>', D3_TAG + '</head>', 1)

# ── 2. Inject SELLER_DATA before var SELLERS ──
SELLER_DATA_INJECT = f'var SELLER_DATA = {seller_data_raw};\n'
if 'window.SELLER_DATA' not in html and 'var SELLER_DATA' not in html:
    html = html.replace('var SELLERS = [', SELLER_DATA_INJECT + 'var SELLERS = [', 1)

# ── 3. Update doExecute() ──
OLD_EXECUTE = '''function doExecute(){
  // TODO: 執行查詢，結果顯示於 Outcome 區塊
  var s=_sel.seller, b=_sel.buyer;
  var d1=document.getElementById('date1').value;
  var d2=document.getElementById('date2').value;
  var out=document.getElementById('outcome-inner');
  if(!s&&!b){out.textContent='⚠ 請先選擇 Seller 或 Buyer';return;}
  out.textContent='查詢中… Seller='+(s||'—')+' Buyer='+(b||'—')+' From='+d1+' To='+d2;
}'''

NEW_EXECUTE = '''function doExecute(){
  var s=_sel.seller, b=_sel.buyer;
  var d1=document.getElementById('date1').value;
  var d2=document.getElementById('date2').value;
  if(!s&&!b){
    document.getElementById('outcome-inner')&&
    (document.getElementById('outcome-inner').textContent='⚠ 請先選擇 Seller 或 Buyer');
    return;
  }
  // Seller mindmap
  if(s){
    renderSellerMindmap(s,d1,d2);
    return;
  }
  // Buyer (future)
  var out=document.getElementById('outcome');
  out.innerHTML='<div id="outcome-inner" style="text-align:center;color:#0055aa;font-size:20px;padding:40px;">Buyer 查詢功能開發中…</div>';
}'''

if OLD_EXECUTE in html:
    html = html.replace(OLD_EXECUTE, NEW_EXECUTE)
    print("✓ doExecute() updated")
else:
    print("⚠ doExecute() not found — checking partial match...")
    # Try finding the function by simpler pattern
    m = re.search(r'function doExecute\(\)\{.*?\}', html, re.DOTALL)
    if m:
        print("Found doExecute at:", m.start(), "-", m.end())
        print("Content:", m.group()[:200])
    else:
        print("NOT found")

# ── 4. Add renderSellerMindmap function before </script> ──
MINDMAP_JS = r'''
// ─── Seller Mindmap ────────────────────────────────────────────────────────
function renderSellerMindmap(sellerName, d1, d2){
  var out=document.getElementById('outcome');
  var sd=(window.SELLER_DATA||{})[sellerName];
  if(!sd){
    out.innerHTML='<div id="outcome-inner" style="text-align:center;color:#0055aa;font-size:22px;padding:60px;">查無賣家資料：'+sellerName+'</div>';
    return;
  }

  // ── Date filter: compare as YYYYMMDD integers ──
  var d1i=d1?parseInt(d1.replace(/-/g,'')):0;
  var d2i=d2?parseInt(d2.replace(/-/g,'')):99991231;

  var bAmt={},bDaysSum={},bDaysCnt={};
  (sd.afh.tx||[]).forEach(function(tx){
    if(tx[1]<d1i||tx[1]>d2i) return;
    var n=sd.afh.buyers[tx[0]];
    if(!bAmt[n]){bAmt[n]=0;bDaysSum[n]=0;bDaysCnt[n]=0;}
    bAmt[n]+=tx[2];
    if(tx[3]>0){bDaysSum[n]+=tx[3];bDaysCnt[n]++;}
  });

  var histBuyers=Object.keys(bAmt).map(function(n){
    return{name:n,total:bAmt[n],
      avgDays:bDaysCnt[n]>0?(bDaysSum[n]/bDaysCnt[n]).toFixed(1):null};
  }).sort(function(a,b){return b.total-a.total;});

  var totalHistAmt=histBuyers.reduce(function(s,b){return s+b.total;},0);
  var allDaysSum=Object.keys(bDaysSum).reduce(function(s,k){return s+bDaysSum[k];},0);
  var allDaysCnt=Object.keys(bDaysCnt).reduce(function(s,k){return s+bDaysCnt[k];},0);
  var overallAvgDays=allDaysCnt>0?(allDaysSum/allDaysCnt).toFixed(1):null;

  // ── Layout constants ──
  var SW=600,SH=75;   // seller box (600×75 as specified)
  var FW=148,FH=42;   // factory
  var BW=190,BH=78;   // buyer-left (3-line tall)
  var CLW=162,CLH=42; // credit limit
  var APW=162,APH=42; // amount purchased
  var BRW=195,BRH=52; // buyer-right (history)
  var DWW=152,DWH=38; // avg days
  var HG=38;          // horizontal gap between columns
  var VG=16;          // vertical gap between rows
  var PAD_T=58;       // top padding
  var PAD_B=36;
  var PAD_L=18;
  var PAD_R=18;
  var HDR_H=26;

  // Flatten WL rows
  var leftRows=[];
  (sd.wl.factories||[]).forEach(function(f){
    f.buyers.forEach(function(b,bi){
      leftRows.push({factory:f.loc,buyer:b.name,cr:b.cr,country:b.country,
        sector:b.sector,cl:b.cl,ap:b.ap,
        isFirst:bi===0,factoryTotal:f.buyers.length});
    });
  });

  var nLeft=leftRows.length, nRight=histBuyers.length;
  var nRows=Math.max(nLeft,nRight,1);
  var rowH=Math.max(BH,CLH,APH,BRH,DWH)+VG;

  // X column centers (absolute from SVG left)
  var apcx =PAD_L+APW/2;
  var clcx =apcx+APW/2+HG+CLW/2;
  var bcx  =clcx+CLW/2+HG+BW/2;
  var fcx  =bcx+BW/2+HG+FW/2;
  var scx  =fcx+FW/2+HG+SW/2;
  var brcx =scx+SW/2+HG+BRW/2;
  var drcx =brcx+BRW/2+HG+DWW/2;
  var svgW =(nRight>0?drcx+DWW/2:scx+SW/2)+PAD_R;

  var contentH=nRows*rowH-VG;
  var svgH=PAD_T+contentH+PAD_B;

  function rowCY(i){return PAD_T+i*rowH+rowH/2;}
  var sCY=(rowCY(0)+rowCY(nRows-1))/2; // seller vertical center

  // ── Helpers ──
  var ns='http://www.w3.org/2000/svg';
  function mk(tag,attr,par){
    var el=document.createElementNS(ns,tag);
    for(var k in attr) el.setAttribute(k,attr[k]);
    if(par) par.appendChild(el);
    return el;
  }
  function addRect(par,cx,cy,w,h,fill,stroke,sw,rx){
    return mk('rect',{x:cx-w/2,y:cy-h/2,width:w,height:h,rx:rx!==undefined?rx:6,
      fill:fill,stroke:stroke||fill,'stroke-width':sw||1},par);
  }
  function addText(par,x,y,text,fill,fz,bold){
    var el=mk('text',{x:x,y:y,'text-anchor':'middle','dominant-baseline':'middle',
      fill:fill||'#000','font-size':fz||'12px','font-weight':bold?'bold':'normal'},par);
    el.textContent=text;
    return el;
  }
  function addLine(par,x1,y1,x2,y2,col,sw){
    return mk('line',{x1:x1,y1:y1,x2:x2,y2:y2,stroke:col||'#003366','stroke-width':sw||1.5},par);
  }
  function addBezier(par,x1,y1,x2,y2,col,sw){
    var mx=(x1+x2)/2;
    return mk('path',{d:'M'+x1+','+y1+' C'+mx+','+y1+' '+mx+','+y2+' '+x2+','+y2,
      fill:'none',stroke:col||'#003366','stroke-width':sw||1.8},par);
  }
  function trunc(s,n){return s&&s.length>n?s.slice(0,n-1)+'\u2026':s||'';}
  function fmtAmt(v){
    if(!v&&v!==0) return '\u2014';
    if(v>=1e9) return '$'+(v/1e9).toFixed(2)+'B';
    if(v>=1e6) return '$'+(v/1e6).toFixed(2)+'M';
    if(v>=1e3) return '$'+(v/1e3).toFixed(1)+'K';
    return '$'+Math.round(v).toLocaleString();
  }

  // ── Create SVG ──
  out.innerHTML='<div id="seller-mindmap" style="width:100%;overflow-x:auto;overflow-y:auto;background:#ACD6FF;padding:20px 10px;box-sizing:border-box;"></div>';
  var svg=mk('svg',{width:svgW,height:svgH,style:'background:#ACD6FF;display:block;'},
    document.getElementById('seller-mindmap'));

  // ── Column headers ──
  var hdrY=PAD_T/2;
  function hdrBox(x,y,w,text,fill){
    addRect(svg,x,y,w,HDR_H,fill,fill,0,5);
    addText(svg,x,y,text,'white','11px',true);
  }
  if(nLeft>0){
    hdrBox(clcx,hdrY,CLW,'Total CL: '+fmtAmt(sd.wl.totalCL),'#b08820');
    hdrBox(apcx,hdrY,APW,'Total AP(WL): '+fmtAmt(sd.wl.totalAP),'#b04818');
  }
  if(nRight>0){
    hdrBox(brcx,hdrY,BRW,'Total Purchased: '+fmtAmt(totalHistAmt),'#0055aa');
    if(overallAvgDays) hdrBox(drcx,hdrY,DWW,'Overall Avg: '+overallAvgDays+' days','#2d8855');
  }

  // ── Seller box ──
  addRect(svg,scx,sCY,SW,SH,'#003366','#001d3d',2,8);
  addText(svg,scx,sCY,trunc(sellerName,42),'white','20px',true);

  // ── Left tree ──
  var factoryMap={};
  leftRows.forEach(function(r,ri){
    if(!factoryMap[r.factory]) factoryMap[r.factory]={rows:[]};
    factoryMap[r.factory].rows.push(ri);
  });

  leftRows.forEach(function(r,ri){
    var cy=rowCY(ri);
    // Amount Purchased (AP) box — orange
    addRect(svg,apcx,cy,APW,APH,'#e87722','#c05520',1,5);
    addText(svg,apcx,cy-10,'Amount Purchased','white','10px');
    addText(svg,apcx,cy+10,fmtAmt(r.ap),'white','13px',true);
    // Credit Limit (CL) box — gold
    addRect(svg,clcx,cy,CLW,CLH,'#f0c040','#c09830',1,5);
    addText(svg,clcx,cy-10,'Credit Limit','#333','10px');
    addText(svg,clcx,cy+10,fmtAmt(r.cl),'#444','13px',true);
    // Buyer box — white with dark border
    addRect(svg,bcx,cy,BW,BH,'white','#003366',1.5,6);
    addText(svg,bcx,cy-20,trunc(r.buyer,22),'#003366','11.5px',true);
    addText(svg,bcx,cy,   'CR: '+r.cr+'  |  '+r.country,'#445566','10.5px');
    addText(svg,bcx,cy+20,trunc(r.sector,26),'#667788','10px');
    // Lines: AP — CL — Buyer
    addLine(svg,apcx+APW/2,cy,clcx-CLW/2,cy);
    addLine(svg,clcx+CLW/2,cy,bcx-BW/2,cy);
  });

  // Draw factories
  var drawnF={};
  leftRows.forEach(function(r){
    if(drawnF[r.factory]) return;
    drawnF[r.factory]=true;
    var fg=factoryMap[r.factory];
    var topCY=rowCY(fg.rows[0]), botCY=rowCY(fg.rows[fg.rows.length-1]);
    var fcy=(topCY+botCY)/2;
    var fh=Math.max(FH, botCY-topCY+BH+4);
    // Factory box — blue
    addRect(svg,fcx,fcy,FW,fh,'#0066CC','#004499',1.5,7);
    // Factory label (wrap at ~16 chars)
    var fl=r.factory||'—';
    if(fl.length<=18){
      addText(svg,fcx,fcy,trunc(fl,20),'white','11px',true);
    } else {
      var sp=fl.lastIndexOf(' ',Math.floor(fl.length/2)+4);
      if(sp<1) sp=Math.floor(fl.length/2);
      addText(svg,fcx,fcy-9,trunc(fl.slice(0,sp),20),'white','10.5px',true);
      addText(svg,fcx,fcy+9,trunc(fl.slice(sp+1),20),'white','10.5px',true);
    }
    // Connect factory → seller (bezier)
    addBezier(svg,fcx+FW/2,fcy,scx-SW/2,sCY,'#003366',1.8);
    // Connect factory left → each buyer right
    fg.rows.forEach(function(ri2){
      var bcy=rowCY(ri2);
      addLine(svg,fcx-FW/2,bcy,bcx+BW/2,bcy,'#003366',1.5);
    });
  });

  // ── Right tree ──
  histBuyers.forEach(function(b,ri){
    var cy=rowCY(ri);
    // Buyer-right box — white with dark border
    addRect(svg,brcx,cy,BRW,BRH,'white','#003366',1.5,6);
    addText(svg,brcx,cy-13,trunc(b.name,24),'#003366','11.5px',true);
    addText(svg,brcx,cy+11,fmtAmt(b.total),'#e87722','13px',true);
    // Avg days box — green
    if(b.avgDays){
      addRect(svg,drcx,cy,DWW,DWH,'#44aa66','#2d8855',1,5);
      addText(svg,drcx,cy-9,'Avg Business Days','white','10px');
      addText(svg,drcx,cy+9,b.avgDays+' days','white','12px',true);
      addLine(svg,brcx+BRW/2,cy,drcx-DWW/2,cy,'#003366',1.5);
    }
    // Seller → buyer bezier
    addBezier(svg,scx+SW/2,sCY,brcx-BRW/2,cy,'#0055aa',1.8);
  });
}
// ─── End Seller Mindmap ────────────────────────────────────────────────────
'''

if 'renderSellerMindmap' not in html:
    html = html.replace('</script>', MINDMAP_JS + '\n</script>', 1)
    print("✓ renderSellerMindmap added")
else:
    print("✓ renderSellerMindmap already present")

# ── 5. Save ──
with open('/tmp/inquiry.html', 'w', encoding='utf-8') as f:
    f.write(html)
print(f"Saved /tmp/inquiry.html ({len(html)//1024} KB)")

import shutil
shutil.copy('/tmp/inquiry.html', '/root/.openclaw-cooper/workspace/inquiry/inquiry.html')
print("Saved workspace copy")
