1import{r as f,j as t,u as Is,L as Kn}from"./react-vendor-xjz46aeH.js";import{k as O,f as X,g as ee,v as oe,B as D,z as F,c as Hn,D as be,m as G,C as xe,aT as Se,q as qn,aU as Vn,A as Q,az as Gn,aH as Zn,aI as Yn,aJ as Qn,aK as Jn,aV as Xn,aD as er,aE as tr,aF as sr,aG as nr,E as rr,K as ar,F as Ke,aW as Dt,aX as ir,o as $s,j as or,P as lr}from"./index-DB-GErVi.js";import{m as Ee,e as Ls,i as Ms,a as Ie,u as cr,h as dr,r as Ds,j as Ps,M as $e,k as He,b as ur,A as mr,l as xr,S as pr,R as hr,d as fr}from"./useActivityView-DC6hk5qt.js";import{u as gr}from"./useCopyToClipboard-D3JgiyXp.js";import{r as Bs,t as yr,s as br,e as jr,f as vr,u as Nr,g as wr}from"./useRecommendationMutations-DX2tnWAt.js";import{u as kr}from"./index-DctxNkkm.js";import{T as Sr}from"./TypeToConfirmInput-PzKwsIrP.js";import{d as ce,c as se,b as de,k as Os}from"./tanstack-vendor-CK-H18W-.js";import{a as Cr}from"./actionFailure-B9bV-6re.js";import{d as Pt,e as _r,S as Rr,b as Ar}from"./ScheduleForm-DF6Nu7DE.js";import{d as Er}from"./useScheduleMutations-PQs2EhM9.js";import{u as Tr}from"./useCloudAccountPermissions-Czyj3T8i.js";import{e as Ir}from"./encodeUIDsParam-VbhU02I5.js";import{b as le,d as ct,e as $r}from"./dateUtils-BLHMZBe5.js";import{R as Lr,A as Mr}from"./purchaseType-CIa57y6h.js";import{s as dt,u as ut,h as Dr,c as Pr,S as Ce,a as ie,i as Br,j as Or,k as Fr,V as mt,l as xt,r as pt,f as st,m as Ur,n as Fs,b as Us,C as zr,d as Wr,o as Kr,p as Hr}from"./recBadges-DKOkRq-w.js";import{P as qr}from"./Pagination-CrLnsmAm.js";import{I as Bt}from"./InfoTooltip-I_YM7wGk.js";import{C as nt}from"./CopyableUID-0V37iUnh.js";import{u as Vr}from"./useDebouncedValue-BGg0Nx9L.js";import{u as Gr,a as ht,b as Zr}from"./useJiraIntegration-CbZz77_N.js";import{u as Yr}from"./useServiceNowIntegration-BsrBoaZI.js";import{A as zs}from"./AssigneeSelect-BrJlNLh-.js";import{S as Qr}from"./SearchableSelect-DyTTeEMu.js";import{j as Ws,k as Jr,l as Xr}from"./useRecommendations-aDh5BAyi.js";(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{};e.SENTRY_RELEASE={id:"53c0c37b9d0458a05694e8ed0430da9c4ec6eaca"};var s=new e.Error().stack;s&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[s]="a5db2938-992b-4b0b-af8b-0726562bba0b",e._sentryDebugIdIdentifier="sentry-dbid-a5db2938-992b-4b0b-af8b-0726562bba0b")}catch{}})();const Ot={to:"rounded-md border px-1.5 py-px font-mono text-[13px] border-success-400/40 bg-success-400/10 text-success-700 hover:border-success-500/60",from:"rounded-md border px-1.5 py-px font-mono text-[13px] border-border-strong/60 bg-surface-tertiary/50 text-text-secondary hover:border-primary-600/40 hover:text-primary-600",resource:"font-semibold underline decoration-dotted decoration-text-muted underline-offset-4 hover:text-primary-600 hover:decoration-primary-600"};function ea({kind:e,text:s,rec:n}){const{copy:r,copied:a}=gr(),i=o=>{o.stopPropagation(),r(s,{silent:!0}),X(ee.REC_TITLE_TOKEN_COPIED,{rule_id:n?.ruleId,category:n?.category,token:e})};return t.jsx(O,{content:a?"Copied":`Copy ${s}`,children:t.jsx("button",{type:"button",onClick:i,"aria-label":`Copy ${s}`,"data-token":e,className:`inline-flex max-w-full items-baseline align-baseline transition-colors cursor-pointer ${Ot[e]??Ot.from}`,children:t.jsx("span",{className:"truncate max-w-[11rem] sm:max-w-[18rem]",children:s})})})}function ta({rec:e,className:s=""}){const n=Bs(e),r=f.useMemo(()=>yr(jr(e),{...br(e)??{},resource:n}),[e,n]);return r.length?t.jsx("h3",{className:`min-w-0 break-words text-base font-semibold leading-snug text-text-primary ${s}`,"data-testid":"rec-action-title","data-title-shape":vr(e),children:r.map((a,i)=>a.kind==="from"||a.kind==="to"||a.kind==="resource"?t.jsx(ea,{kind:a.kind,text:a.text,rec:e},i):a.kind==="arrow"?t.jsx("span",{className:"text-text-muted font-normal",children:a.text},i):t.jsx("span",{children:a.text},i))}):null}const sa={pending:"neutral",running:"info",awaiting_user:"warning",succeeded:"success",completed:"success",failed:"danger",cancelled:"neutral",skipped:"neutral"},na={pending:"Pending",running:"Running",awaiting_user:"Action needed",succeeded:"Done",completed:"Done",failed:"Failed",cancelled:"Cancelled",skipped:"Skipped"};function ra({status:e,label:s}){const n=sa[e]||"neutral",r=s||na[e]||e||"";return t.jsx(oe,{variant:n,children:r})}const aa=[{match:/no rows in result set|GetCloudAccountPermission|cloud[_ ]?account.*(not found|missing)/i,summary:"Cloud account is no longer connected",advice:"The cloud account this workflow targets is missing or has been disconnected. Reconnect it in Cloud Estate â Cloud Accounts and start the remediation again."},{match:/missing required field|step input missing/i,summary:"Workflow definition is incomplete",advice:"The remediation template for this recommendation is missing required configuration. This is usually a platform issue â please contact ZopNight support with the workflow ID."},{match:/precondition failed.*discoverer_unavailable/i,summary:"Cloud-state cache is temporarily unavailable",advice:"We couldnât reach the discoverer cache to verify the resourceâs current state. This is usually transient â please retry in a minute. If it keeps failing, check the ZopNight status page or contact support.",transient:!0},{match:/precondition failed.*permission_denied/i,summary:"ZopNight doesnât have permission to read this resourceâs state",advice:"ZopNight doesnât have permission to read the resource state for this remediation. Update the IAM role/service account, then retry."}
1,{match:/precondition failed.*observed\s+["']?not_found/i,summary:"Resource was already deleted",advice:"The target resource is no longer indexed by ZopNightâs discoverer cache â it was likely deleted between recommendation generation and execution. Dismiss this recommendation if the deletion was intentional, or re-run discovery if you believe it should still exist."},{match:/precondition failed.*resource[_ ]?state/i,summary:"Resource is no longer in the expected state",advice:"The target resource has drifted (e.g. already stopped, terminated, or its tags changed) since the recommendation was generated. Re-run discovery or dismiss the recommendation if it no longer applies."},{match:/rejected by .+:/i,summary:"Rejected by an admin",advice:null},{match:/timeout|deadline exceeded/i,summary:"The cloud provider didnât respond in time",advice:"The provider API timed out. This is usually transient â try again in a minute. If it keeps failing, check the providerâs status page."},{match:/permission denied|unauthorized|unauthenticated|forbidden|access denied|not authorized/i,summary:"ZopNight doesnât have permission to act on this resource",advice:"Update the IAM role or service account to grant the actions listed in the recommendation, then retry."}],Ft="The remediation could not complete",Ut="Review the technical details below or contact support if this keeps happening.";function Ks(e){const s=String(e||"").trim();if(!s)return{summary:Ft,advice:Ut,raw:"",transient:!1};for(const n of aa)if(n.match.test(s))return{summary:n.summary,advice:n.advice,raw:s,transient:!!n.transient};return{summary:Ft,advice:Ut,raw:s,transient:!1}}function ia({title:e,subtitle:s,children:n,footer:r,testId:a}){return t.jsxs("div",{"data-testid":a,className:"rounded-md border border-border-strong bg-surface-tertiary/40 px-4 py-3",children:[(e||s)&&t.jsxs("div",{className:"mb-2",children:[e&&t.jsx("h3",{className:"text-sm font-semibold text-text-primary",children:e}),s&&t.jsx("p",{className:`text-xs text-text-secondary ${e?"mt-0.5":""}`,children:s})]}),t.jsx("div",{className:"space-y-3",children:n}),r&&t.jsx("div",{className:"mt-4 flex flex-wrap justify-end gap-2",children:r})]})}function oa({defaultRules:e=[],existingRules:s=[],mode:n="adopt"}){const r=Array.isArray(s)&&s.length>0,a=la({defaultRules:e,existingRules:s,mode:n,hasExisting:r}),i=r&&n==="replace",o=r&&n==="adopt",l=r,c=r&&n==="adopt"?"Effective (merged)":"Rules to apply",d=(o?1:0)+(l?1:0)+1,u=d===3?"grid-cols-3":d===2?"grid-cols-2":"grid-cols-1";return t.jsx("div",{"data-testid":"lifecycle-policy-preview",className:"rounded-md border border-border bg-surface",children:t.jsxs("div",{className:`grid gap-px bg-border ${u}`,children:[o&&t.jsx(qe,{title:"Default rules we'd add",testId:"lifecycle-default-column",children:t.jsx(Ve,{rules:e,emptyMessage:"No default rules configured."})}),l&&t.jsx(qe,{title:i?"Existing rules (will be removed)":"Your existing rules",testId:"lifecycle-existing-column",children:t.jsx(Ve,{rules:s,emptyMessage:"No existing rules.",testIdPrefix:"lifecycle-existing-row",markRemoved:i})}),t.jsx(qe,{title:c,testId:"lifecycle-effective-column",highlight:!0,children:t.jsx(Ve,{rules:a,emptyMessage:"No rules would apply.",testIdPrefix:"lifecycle-effective-row"})})]})})}function qe({title:e,testId:s,highlight:n,children:r}){return t.jsxs("div",{"data-testid":s,className:`px-3 py-2 ${n?"bg-warning-400/5":"bg-surface"}`,children:[t.jsx("p",{className:`mb-2 text-xs font-semibold ${n?"text-warning-700":"text-text-secondary"}`,children:e}),r]})}function Ve({rules:e,emptyMessage:s,testIdPrefix:n,markRemoved:r=!1}){if(!Array.isArray(e)||e.length===0)return t.jsx("p",{className:"text-xs italic text-text-muted",children:s});const a=r?"Existing lifecycle rules â will be removed":void 0;return t.jsxs("table",{"aria-label":a,className:"w-full border-separate border-spacing-y-1 text-xs",children:[t.jsx("thead",{className:"sr-only",children:t.jsxs("tr",{children:[t.jsx("th",{scope:"col",children:"Action"}),t.jsx("th",{scope:"col",children:"When"})]})}),t.jsx("tbody",{children:e.map((i,o)=>{const{kind:l,daysAfter:c}=i?.action||{},d=`${i?.name||"rule"}-${l||"action"}-${c??o}`,u=r?`${zt(i)} after ${Wt(c)} â will be removed`:void 0;return t.jsxs("tr",{"data-testid":n?`${n}-${o}`:void 0,"aria-label":u,className:`leading-snug ${r?"text-text-muted line-through":"text-text-secondary"}`,children:[t.jsx("td",{className:`pr-2 align-top font-medium ${r?"":"text-text-primary"}`,children:zt(i)}),t.jsxs("td",{className:"align-top whitespace-nowrap",children:[t.jsxs("span",{children:["after ",Wt(c)]}),r&&t.jsx("span",{"data-testid":n?`${n}-${o}-removed-badge`:void 0,className:"ml-1.5 inline-flex items-center rounded bg-warning-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-warning-700 no-underline",children:"Removed"})]})]},d)})})]})}function la({defaultRules:e,existingRules:s,mode:n,hasExisting:r}){if(n==="replace"||!r)return Array.isArray(e)?e:[];const a=new Set,i=[],o=l=>{if(!l)return;const c=l.action||{},d=`${c.kind||""}::${c.daysAfter??""}`;a.has(d)||(a.add(d),i.push(l))};for(const l of s)o(l);for(const l of e)o(l);return i}function zt(e){const s=e?.action||{};return s.kind==="tierTransition"?`Transition â ${s.targetTier||"storage class"}`:s.kind==="delete"?"Delete object":s.kind||"Lifecycle action"}function Wt(e){return typeof e!="number"||!Number.isFinite(e)?"unspecified age":e===1?"1 day":`${e} days`}function ca({step:e,onAdvance:s,isAdvancing:n=!1}){const r=e?.input||{},a=typeof r.impactSummary=="string"?r.impactSummary:"",i=Array.isArray(r.previewImpact)?r.previewImpact:[],o=typeof r.educateCopy=="str
1ing"?r.educateCopy:"",l=typeof r.confirmValue=="string"?r.confirmValue:"",c=typeof r.confirmPrompt=="string"&&r.confirmPrompt.trim().length>0?r.confirmPrompt:`Confirm ${r.resourceType||"resource"} name to proceed`,d=r.isLifecycle===!0,u=Array.isArray(r.defaultRules)?r.defaultRules:[],m=Array.isArray(r.existingRules)?r.existingRules:[],[x,h]=f.useState(""),[p,y]=f.useState("adopt"),b=f.useRef(null),A=`confirm-input-${e?.id||"guided"}`;f.useEffect(()=>{l&&b.current?.focus()},[l]);const N=l.trim().length>0&&x.trim().toLowerCase()===l.trim().toLowerCase(),k=()=>{if(!N||n)return;const v={confirmedValue:x};d&&(v.patchInput={mode:p}),s?.(v)},j=d?"Pick how the new policy combines with what you already have, then confirm.":"Review impact, acknowledge rebuild cost, then confirm the resource name to proceed.";return t.jsxs(ia,{testId:"guided-review-step",subtitle:j,footer:s?t.jsx(D,{variant:"primary",size:"md",onClick:k,disabled:!N||n,"data-testid":"guided-review-open-confirm",title:N?"":"Type the exact resource name to enable Confirm.",children:n?"Startingâ¦":"Confirm & start"}):null,children:[d?t.jsxs(t.Fragment,{children:[t.jsx(da,{mode:p,onChange:y}),t.jsx(oa,{defaultRules:u,existingRules:m,mode:p})]}):t.jsxs(t.Fragment,{children:[a&&t.jsx("p",{"data-testid":"guided-review-summary",className:"rounded-md border border-warning-400/40 bg-warning-400/10 px-3 py-2 text-xs font-medium text-warning-700",children:a}),i.length>0&&t.jsx("ul",{className:"divide-y divide-border rounded-md border border-border bg-surface",children:i.map((v,L)=>t.jsxs("li",{"data-testid":`guided-review-row-${L}`,className:"flex items-center gap-3 px-3 py-2",children:[t.jsx("span",{className:"text-xs font-medium text-text-primary",children:v?.label}),t.jsx("span",{className:"text-xs text-text-secondary",children:v?.value}),t.jsx("span",{className:"ml-auto",children:t.jsx(ma,{severity:v?.severity})})]},`${L}-${v?.label}`))})]}),o&&(["Reversible","Reversible going forward"].includes(r?.educateHeader)?t.jsxs("div",{"data-testid":"guided-review-reversible-banner",className:"rounded-md border border-warning-400/40 bg-warning-400/10 px-3 py-2 text-xs text-warning-700",children:[t.jsxs("span",{className:"font-semibold",children:[r.educateHeader," · "]}),t.jsx("span",{children:o})]}):t.jsxs("details",{className:"pt-2 border-t border-border",children:[t.jsxs("summary",{className:"cursor-pointer list-none select-none text-xs uppercase tracking-wide text-text-muted",children:[r?.educateHeader||"Why this action is permanent",t.jsx("span",{className:"ml-1 normal-case tracking-normal text-text-muted/60",children:"â details"})]}),t.jsx("div",{className:"mt-2",children:t.jsx(xa,{text:o})})]})),l&&t.jsxs("div",{"data-testid":"guided-review-inline-confirm",role:"group","aria-label":"Type to confirm",className:"space-y-2 pt-2 border-t border-border",children:[t.jsx(Sr,{expected:l,value:x,onChange:v=>h(v.target.value),onConfirm:k,inputRef:b,id:A,label:"Expected value:",isMatch:N}),t.jsx("p",{className:"text-xs text-text-muted",children:c})]})]})}function da({mode:e,onChange:s}){const n=[{value:"adopt",label:"Adopt",hint:"Keep my existing rules, add ZopNight's savings rules on top."},{value:"replace",label:"Replace",hint:"Replace my existing rules with ZopNight's savings rules."}];return t.jsx("fieldset",{"data-testid":"lifecycle-mode-toggle","aria-label":"Lifecycle policy mode",className:"mb-3 grid grid-cols-1 gap-2 sm:grid-cols-2",children:n.map(r=>{const a=e===r.value;return t.jsxs("label",{"data-testid":`lifecycle-mode-${r.value}`,className:`flex cursor-pointer items-start gap-2 rounded-md border px-3 py-2 transition-colors ${a?"border-primary-600/40 bg-primary-600/5":"border-border bg-surface hover:border-border-strong"}`,children:[t.jsx("input",{type:"radio",name:"lifecycle-mode",value:r.value,checked:a,onChange:()=>s(r.value),className:"mt-0.5 h-4 w-4 cursor-pointer accent-primary-600"}),t.jsxs("span",{className:"flex flex-col",children:[t.jsx("span",{className:"text-xs font-semibold text-text-primary",children:r.label}),t.jsx("span",{className:"text-xs text-text-secondary",children:r.hint})]})]},r.value)})})}const Kt={critical:"border-danger-400/40 bg-danger-400/10 text-danger-600",high:"border-warning-400/40 bg-warning-400/15 text-warning-700",medium:"border-warning-400/30 bg-warning-400/10 text-warning-700",low:"border-neutral-400/40 bg-neutral-400/10 text-text-muted"},ua={critical:"Critical",high:"High",medium:"Medium",low:"Low"};function ma({severity:e}){const s=Kt[e]||Kt.low,n=ua[e]||"Info";return t.jsx("span",{"data-testid":"severity-badge",className:`inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${s}`,children:n})}function xa({text:e}){const s=pa(e);return t.jsx("div",{"data-testid":"guided-review-copy",className:"space-y-2 text-sm leading-relaxed text-text-secondary",children:s.map((n,r)=>n.type==="list"?t.jsx("ul",{className:"list-disc pl-5 space-y-1",children:n.items.map((a,i)=>t.jsx("li",{children:a},i))},r):t.jsx("p",{children:n.text},r))})}function pa(e){return e?e.replace(/\r\n/g,` 2`).split(/\n\s*\n/).map(n=>
2n.trim()).filter(Boolean).map(n=>{const r=n.split(` 3`).map(i=>i.trim());return r.length>0&&r.every(i=>i.startsWith("- "))?{type:"list",items:r.map(i=>i.replace(/^- /,""))}:{type:"paragraph",text:n}}):[]}const ha={precondition:"auto",approval:"admin",execute:"auto",validate:"auto",manual:"you do this",notify:"auto",guided_review:"you confirm"},fa={auto:{label:"ZopNight",variant:"info"},admin:{label:"Admin",variant:"warning"},"you do this":{label:"You",variant:"neutral"},"you confirm":{label:"You",variant:"neutral"}},ga=new Set(["guided_review"]);function ya({step:e,index:s,isLast:n,onAdvance:r,isAdvancing:a=!1}){const i=e.status==="failed",o=e.status==="awaiting_user",l=ha[e.kind]||e.kind||"auto",c=fa[l]||{label:"ZopNight",variant:"info"},d=ga.has(e.kind),u=e.input?.downtimeBanner,m=e.kind==="approval"&&typeof u=="string"&&u.length>0?u:null,x=e.status==="completed"||e.status==="succeeded",h=e.output?.note,p=x&&typeof h=="string"&&h.length>0?h:null;return t.jsxs("div",{className:"flex gap-3","data-testid":`workflow-step-${s}`,children:[t.jsxs("div",{className:"flex flex-col items-center",children:[t.jsx(ka,{status:e.status}),!n&&t.jsx("div",{className:"w-px flex-1 bg-border-strong"})]}),t.jsxs("div",{className:"flex-1 pb-4",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.jsxs("span",{className:"text-sm font-medium text-text-primary",children:[s+1,". ",e.name]}),t.jsx(oe,{variant:c.variant,children:c.label}),t.jsx("div",{className:"ml-auto",children:t.jsx(ra,{status:e.status})})]}),e.description&&t.jsx("p",{className:"mt-1 text-xs text-text-secondary",children:e.description}),m&&t.jsx("p",{role:"note","data-testid":"approval-downtime-banner",className:"mt-2 rounded-md border border-warning-400/40 bg-warning-400/10 px-3 py-2 text-xs font-medium text-warning-700",children:m}),p&&t.jsx("p",{role:"note","data-testid":"step-success-note",className:"mt-2 rounded-md border border-info-400/40 bg-info-400/10 px-3 py-2 text-xs font-medium text-info-700",children:p}),i&&(e.errorMessage||e.errorRaw)&&t.jsx(ba,{summary:e.errorMessage,raw:e.errorRaw,category:e.errorCategory,fixHint:e.errorFixHint,consoleUrl:e.errorConsoleUrl,guidance:e.errorGuidance}),o&&e.kind==="manual"&&t.jsx("p",{className:"mt-2 text-xs text-warning-700",children:"Complete this step in your cloud console, then mark it done."}),o&&e.kind==="approval"&&t.jsx("p",{className:"mt-2 text-xs text-warning-700",children:"Waiting for an admin in your org to approve."}),o&&d&&t.jsx("div",{className:"mt-2",children:t.jsx(ca,{step:e,onAdvance:r,isAdvancing:a})})]})]})}function ba({summary:e,raw:s,category:n,fixHint:r,consoleUrl:a,guidance:i}){if(!n){const d=Ks(e||s),u=d.raw&&d.raw!==d.summary?d.raw:"";return t.jsxs("div",{className:"mt-2 text-xs",children:[t.jsx("p",{className:"text-danger-500",children:d.summary}),r&&t.jsxs("p",{"data-testid":"step-fix-hint",className:"mt-1.5 rounded-md border border-warning-400/40 bg-warning-400/10 px-3 py-2 text-xs font-medium text-warning-700",children:["How to fix: ",r]}),!r&&d.advice&&t.jsx("p",{className:"mt-1 text-text-secondary leading-relaxed",children:d.advice}),u&&t.jsxs("details",{className:"mt-1 group",children:[t.jsxs("summary",{className:"text-text-muted cursor-pointer hover:text-text-secondary list-none flex items-center gap-1 text-[11px]",children:[t.jsx(qt,{}),"Show technical details"]}),t.jsx("pre",{className:"mt-1 whitespace-pre-wrap break-words text-[11px] font-mono text-text-muted bg-surface-tertiary/60 rounded p-2",children:u})]})]})}const o=Na(n),l=wa(n),c=s&&s.trim()!==(e||"").trim();return t.jsxs("div",{className:`mt-2 flex items-start gap-2 rounded-md border ${o.border} ${o.bg} px-3 py-2 text-xs`,"data-testid":`step-error-${n}`,children:[t.jsx(ja,{category:n,className:`mt-0.5 h-4 w-4 shrink-0 ${o.heading}`}),t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsxs("p",{className:`font-medium ${o.heading}`,children:[l," ",t.jsx("span",{className:"font-normal",children:e})]}),i?t.jsx(va,{guidance:i,fallbackConsoleUrl:a}):t.jsxs(t.Fragment,{children:[r&&t.jsxs("p",{"data-testid":"step-fix-hint",className:"mt-1.5 rounded-md border border-warning-400/40 bg-warning-400/10 px-3 py-2 text-xs font-medium text-warning-700",children:["How to fix: ",r]}),a&&t.jsx("a",{href:a,target:"_blank",rel:"noreferrer noopener",className:`mt-1.5 inline-block text-[11px] font-medium ${o.linkText} hover:underline`,children:"Open cloud console â"})]}),c&&t.jsxs("details",{className:"mt-1.5 group",children:[t.jsxs("summary",{className:"text-text-muted cursor-pointer hover:text-text-secondary list-none flex items-center gap-1 text-[11px]",children:[t.jsx(qt,{}),"Show technical details"]}
3),t.jsx("pre",{className:"mt-1 whitespace-pre-wrap break-words text-[11px] font-mono text-text-muted bg-surface-tertiary/60 rounded p-2",children:s})]})]})]})}function ja({category:e,className:s}){return e==="transient"?t.jsx("svg",{className:s,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,"aria-hidden":!0,children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})}):e==="system"?t.jsx("svg",{className:s,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,"aria-hidden":!0,children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v3.75m0 3.75h.008M9.172 5.172a4 4 0 015.656 0M12 3v.01M4.93 19h14.14a2 2 0 001.84-2.75L13.84 4.5a2 2 0 00-3.68 0L3.09 16.25A2 2 0 004.93 19z"})}):t.jsx("svg",{className:s,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,"aria-hidden":!0,children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"})})}function va({guidance:e,fallbackConsoleUrl:s}){const{kind:n,role:r,permissions:a=[],scope:i,steps:o=[],consoleUrl:l,consoleLabel:c}=e||{},d=l||s,u=n==="grant";return t.jsxs("div",{className:"mt-2 rounded-md bg-surface-tertiary/60 p-3 text-xs",children:[u?t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"mb-2 text-text-secondary",children:"ZopNight needs permission to do this for you:"}),t.jsxs("dl",{className:"space-y-1.5",children:[r&&t.jsx(Ge,{label:"Role",value:t.jsx("span",{className:"font-semibold text-text-primary",children:r})}),a.length>0&&t.jsx(Ge,{label:"Grants",value:t.jsx("code",{className:"break-all font-mono text-[11px] text-text-secondary",children:a.join(", ")})}),i&&t.jsx(Ge,{label:"Scope",value:t.jsx("span",{className:"text-text-secondary",children:i})})]})]}):t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"mb-1.5 font-medium text-text-secondary",children:"ZopNight canât complete this one automatically. To fix it yourself:"}),t.jsx("ol",{className:"list-decimal space-y-1.5 pl-4 leading-relaxed text-text-secondary",children:o.map((m,x)=>t.jsx("li",{children:m},x))})]}),d&&t.jsxs("a",{href:d,target:"_blank",rel:"noreferrer noopener",className:"mt-3 inline-flex items-center gap-1.5 rounded-md bg-primary-600 px-3 py-1.5 text-[11px] font-semibold text-text-inverse hover:bg-primary-700",children:[c||(u?"Grant access":"Open in cloud console"),t.jsx("span",{"aria-hidden":!0,children:"â"})]}),u&&t.jsxs("p",{className:"mt-2 text-[11px] text-text-muted",children:["After granting, come back and click"," ",t.jsx("span",{className:"font-medium text-text-secondary",children:"Remediate again"}),"."]})]})}function Ge({label:e,value:s}){return t.jsxs("div",{className:"flex gap-3",children:[t.jsx("dt",{className:"w-14 shrink-0 text-text-muted",children:e}),t.jsx("dd",{className:"min-w-0 flex-1",children:s})]})}const Ht={user_action:{border:"border-warning-400/40",bg:"bg-warning-400/10",heading:"text-warning-700",linkText:"text-warning-700"},transient:{border:"border-info-400/40",bg:"bg-info-400/10",heading:"text-info-700",linkText:"text-info-700"},system:{border:"border-danger-400/40",bg:"bg-danger-400/10",heading:"text-danger-600",linkText:"text-danger-600"}};function Na(e){return Ht[e]||Ht.system}function wa(e){switch(e){case"user_action":return"Action needed:";case"transient":return"Try again:";default:return"Couldn't complete:"}}function qt(){return t.jsx("svg",{className:"w-3 h-3 transition-transform group-open:rotate-90",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:"2","aria-hidden":!0,children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9 5l7 7-7 7"})})}function ka({status:e}){const s=e==="running"||e==="completed"||e==="succeeded"||e==="awaiting_user"||e==="failed",n=e==="failed"?"bg-danger-500":e==="awaiting_user"?"bg-warning-700":e==="running"?"bg-primary-600":e==="completed"||e==="succeeded"?"bg-success-600":"bg-neutral-400/40";return t.jsx("span",{className:`mt-1 inline-block h-3 w-3 rounded-full ${s?n:"border border-neutral-400/60"}`,"aria-hidden":!0})}function Vt({steps:e=[],emptyMessage:s="No steps planned.",onAdvanceStep:n,isAdvancing:r=!1,advancedStepId:a=null}){return e.length?t.jsx("div",{className:"flex flex-col","data-testid":"workflow-step-list",children:e.map((i,o)=>{const l=Sa(i),c=n?d=>n({step:l,payload:d}):void 0;return t.jsx(ya,{step:l,index:o,isLast:o===e.length-1,onAdvance:c,isAdvancing:r||a!=null&&l.id===a},`${o}-${i.name||i.kind}`)})}):t.jsx("p",{className:"text-sm text-text-secondary",children:s})}function Sa(e){const s=e.input??{};return{id:e.id,name:e.name||e.kind,kind:e.kind||"execute",description:e.description,status:e.status||"pending",errorMessage:e.errorMessage,userActionRequired:e.userActionRequired,errorRaw:e.errorRaw,errorCategory:e.errorCategory,errorFixHint:e.errorFixHint,errorConsoleUrl:e.errorConsoleUrl,errorRetryable:e.errorRetryable,errorGuidance:e.errorGuidance,output:{...e.output??{},note:e.output?.note},input:{...s,previewImpact:s.previewImpact,impactSummary:s.impactSummary,educateCopy:s.educateCopy,confirmType:s.confirmType,confirmValue:s.confirmValue}}}function Ca({count:e=3}){if(e<=0)return null;const s=Array.from({length:e});return t.jsx("div",{className:"flex flex-col","data-testid":"workflow-step-skeleton",children:s.map((n,r)=>{const a=r===s.length-1;return t.jsxs("div",{className:"flex gap-3",children:[t.jsxs("div",{className:"flex flex-col items-center",children:[t.jsx("span",{className:"mt-1 inline-block h-3 w-3 rounded-full bg-surface-tertiary animate-pulse"}),!a&&t.jsx("div",{className:"w-px flex-1 bg-border-strong"})]}),t.jsxs("div",{className:"flex-1 pb-4",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("div",{className:"h-4 w-2/5 rounded bg-surface-tertiary animate-pulse"}),t.jsx("div",{className:"ml-auto h-4 w-16 rounded bg-surface-tertiary animate-pulse"})]}),t.jsx("div",{className:"mt-2 h-3 w-3/4 rounded bg-surface-tertiary animate-pulse"})]})]},r)})})}const Gt="Estimated from public list price â your actual bill may differ, and this is a projection, not a measurement.",Rd="projected from public list price, not from your bill";function _a(e){const s=e?.lastReevaluatedAt??e?.updatedAt??null;if(!s)return"";const n=new Date(s);return Number.isNaN(n.getTime())?"":n.toLocaleDateString(void 0,{month:"short",day:"numeric",year:"numeric"})}function Ra(e){const s=_a(e);return s?`${Gt} Priced ${s}.`:Gt}const q={all:["remediation"],preview:e=>["remediation","preview",e],workflow:e=>["remediation","workflow",e],pendingApprovals:["remediation","pending-approvals"],pendingConfirmations:["remediation","pending-confirmations"]};function Aa(e,{enabled:s=!0}={}){return ce({queryKey:q.preview(e),queryFn:()=>
3F.get(`/recommendations/${e}/workflow`),enabled:!!(e&&s),staleTime:5e3})}function Ea(){const e=se();return de({mutationFn:({recId:s})=>F.post(`/recommendations/${s}/workflow`,{}),onSuccess:()=>{X(ee.REMEDIATION_ACTION_SUCCEEDED,{operation:"start"}),e.invalidateQueries({queryKey:["recommendations"]})},onError:s=>{X(ee.REMEDIATION_ACTION_FAILED,{operation:"start",...Cr(s)})}})}function Zt(e,{enabled:s=!0}={}){const n=se();return ce({queryKey:q.workflow(e),queryFn:async()=>{const r=await F.get(`/workflows/${e}`);return r&&Le(r.status)&&n.invalidateQueries({queryKey:["recommendations"]}),r},enabled:!!(e&&s),refetchInterval:r=>{const a=r.state.data;if(!a)return 3e3;if(Le(a.status))return!1;const i=a.createdAt?new Date(a.createdAt).getTime():Date.now();return Date.now()-i>120*1e3?1e4:3e3},refetchIntervalInBackground:!0})}function Le(e){return e==="completed"||e==="failed"||e==="cancelled"||e==="succeeded"}function Ad({enabled:e=!0}={}){return ce({queryKey:q.pendingApprovals,queryFn:async()=>{const s=await F.get("/workflows/pending-approval");return Array.isArray(s)?s:[]},enabled:!!e,refetchInterval:3e4,refetchOnWindowFocus:!0,staleTime:1e4})}function Ed({enabled:e=!0}={}){return ce({queryKey:q.pendingConfirmations,queryFn:async()=>{const s=await F.get("/workflows/pending-confirmation");return Array.isArray(s)?s:[]},enabled:!!e,refetchInterval:3e4,refetchOnWindowFocus:!0,staleTime:1e4})}function Ta(){const e=se();return de({mutationFn:({jobId:s,reason:n})=>{const r=n?{reason:n}:{};return F.post(`/workflows/${encodeURIComponent(s)}/cancel`,r)},onMutate:({jobId:s})=>ft(e,s),onError:(s,n,r)=>gt(e,r),onSettled:(s,n,{jobId:r})=>{e.invalidateQueries({queryKey:q.workflow(r)}),e.invalidateQueries({queryKey:q.pendingApprovals}),e.invalidateQueries({queryKey:["recommendations"]})}})}function Ia(){const e=se();return de({mutationFn:async({jobId:s,stepId:n,confirmedValue:r,patchInput:a})=>{if(typeof r!="string"||r.trim().length===0)throw new Error("confirmedValue is required to advance a guided step");if(!n)throw new Error("stepId is required to advance a guided step");const i={action:"advance",confirmedValue:r};return a&&typeof a=="object"&&Object.keys(a).length>0&&(i.patchInput=a),F.patch(`/workflows/${encodeURIComponent(s)}/steps-by-id/${encodeURIComponent(n)}`,i)},onSettled:(s,n,{jobId:r})=>{e.invalidateQueries({queryKey:q.workflow(r)}),e.invalidateQueries({queryKey:["recommendations"]})}})}function $a(){const e=se();return de({mutationFn:({jobId:s,stepId:n,stepName:r})=>n?F.patch(`/workflows/${encodeURIComponent(s)}/steps-by-id/${encodeURIComponent(n)}`,{action:"approve"}):F.post(`/workflows/${encodeURIComponent(s)}/steps/${encodeURIComponent(r)}/approve`,{}),onMutate:({jobId:s})=>ft(e,s),onError:(s,n,r)=>gt(e,r),onSettled:(s,n,{jobId:r})=>{e.invalidateQueries({queryKey:q.workflow(r)}),e.invalidateQueries({queryKey:q.pendingApprovals}),e.invalidateQueries({queryKey:["recommendations"]})}})}function La(){const e=se();return de({mutationFn:async({jobId:s,stepId:n,stepName:r,reason:a})=>{if(!a||!a.trim())throw new Error("reason is required to reject an approval");return n?F.patch(`/workflows/${encodeURIComponent(s)}/steps-by-id/${encodeURIComponent(n)}`,{action:"reject",reason:a}):F.post(`/workflows/${encodeURIComponent(s)}/steps/${encodeURIComponent(r)}/reject`,{reason:a})},onMutate:({jobId:s})=>ft(e,s),onError:(s,n,r)=>gt(e,r),onSettled:(s,n,{jobId:r})=>{e.invalidateQueries({queryKey:q.workflow(r)}),e.invalidateQueries({queryKey:q.pendingApprovals}),e.invalidateQueries({queryKey:["recommendations"]})}})}function ft(e,s){const n=q.pendingApprovals,r=e.getQueryData(n);return Array.isArray(r)&&e.setQueryData(n,r.filter(a=>a.jobId!==s)),{previous:r}}function gt(e,s){s?.previous!==void 0&&e.setQueryData(q.pendingApprovals,s.previous)}function Ma({open:e,onClose:s,rec:n,readOnly:r=!1}){const[a,i]=kr("workflowId",{defaultValue:""}),o=n?.id,l=Zt(a||null,{enabled:e&&!!a}),c=l.data?.subjectId||"",d=!!(c&&o&&c!==o),u=!!(a&&l.error&&l.error.status===404),m=d||u,x=m?"":a,h=e&&!x,p=Aa(o,{enabled:h}),y=p.data?.activeJobId||p.data?.lastJobId||"",b=x||y||null,A=Zt(y||null,{enabled:e&&!x&&!!y}),N=x?l:A,k=Ea();f.useEffect(()=>{m&&a?i(""):y&&!x&&!m&&i(y)},[m,a,y,x]);const j=f.useRef(!1);f.useEffect(()=>{e||(j.current=!1,k.reset())},[e]);const v=e&&!r&&h&&p.data!=null&&!p.isLoading&&!p.error&&!!(p.data?.canStart&&p.data?.templateId)&&!b&&!k.isPending&&!k.isSuccess;f.useEffect(()=>{v&&!j.current&&(j.current=!0,k.mutate({recId:o},{onSuccess:T=>{T?.jobId&&i(T.jobId)}}))},[v]);const L=()=>{k.mutate({recId:o},{onSuccess:T=>{T?.jobId&&i(T.jobId)}})},U=Ta(),Z=$a(),w=La(),M=Ia(),$=M.isSuccess&&!M.isPending?M.variables?.stepId:null,g=({step:T,payload:W})=>{r||!b||!T?.id||M.isPending||T.id===$||M.mutate({jobId:b,stepId:T.id,confirmedValue:W?.confirmedValue,patchInput:W?.patchInput})},E=Hn(T=>T.email)||"",_=()=>{const T=N.data;(!T||!["completed","failed","cancelled","dlq","deleting","deleted"].includes(T.status))&&X(ee.REMEDIATION_CANCELLED,{rule_id:n?.ruleId});const z=(T?.steps||[]).find(C=>C.status==="awaiting_user"&&C.kind==="guided_review"),H=M.isPending||$!=null&&$===z?.id;!r&&!H&&T&&T.status==="awaiting_user"&&z&&U.mutate({jobId:T.id}),s?.()};return e?t.jsxs(be,{open:e,onClose:_,title:`Remediate: ${n?.title||n?.resourceName||"recommendation"}`,footer:t.jsx(Ba,{readOnly:r,activeJobId:b,workflow:N.data,preview:p.data,rec:n,isStarting:k.isPending,onClose:_,onRestart:L,viewerEmail:E,cancelMutation:U,approveMutation:Z,rejectMutation:w}),children:[r&&t.jsxs("div",{role:"note",className:"mb-4 rounded-lg border border-info-400/30 bg-info-400/10 p-3 text-sm text-info-700",children:[t.jsx("p",{className:"font-medium",children:"View only"}),t.jsx("p",{children:"This is the customer's remediation workflow. Staff can review the steps here but can't run it â the customer initiates it from their own account."})]}),t.jsx(Da,{readOnly:r,rec:n,previewQuery:p,workflowQuery:N,activeJobId:b,startError:k.error,isAutoStarting:k.isPending,onAdvanceStep:g,advancedStepId:$,isAdvancing:M.isPending})]}):null}function Da({readOnly:e,rec:s,previewQuery:n,workflowQuery:r,activeJobId:a,startError:i,isAutoStarting:o,onAdvanceStep:l,advancedStepId:c,isAdvancing:d}){if(a){if(r.isLoading)return t.jsx("p",{className:"text-sm text-text-secondary",children:"Loading workflowâ¦"});if(r.error)return t.jsx(Ne,{message:String(r.error.message||r.error)});const m=r.data;return m?t.jsxs("div",{className:"space-y-4",children:[t.jsx(Ze,{rec:s}),m.errorMessage&&!(m.steps||[]).some(x=>x.errorGuidance)&&t.jsx(Ne,{message:m.errorMessage}),t.jsx(Vt,{steps:m.steps||[],onAdvanceStep:e?void 0:l,isAdvancing:d,advancedStepId:c}),t.jsx(Pa,{workflow:m})]}):null}if(n.isLoading||o)return t.jsxs("div",{className:"space-y-4",children:[t.jsx(Ze,{rec:s}),t.jsx("p",{className:"text-xs uppercase tracking-wide text-text-muted",children:o?"Startingâ¦":"ZopNight will run these steps"}),t.jsx(Ca,{count:3})]});
3if(n.error)return t.jsx(Ne,{message:`Failed to load workflow plan: ${String(n.error.message||n.error)}`});const u=n.data;return!u||!u.templateId?null:t.jsxs("div",{className:"space-y-4",children:[t.jsx(Ze,{rec:s}),u.humanSummary&&t.jsx("p",{className:"text-sm text-text-secondary",children:u.humanSummary}),!u.canStart&&u.cannotStartWhy&&t.jsx(Ne,{variant:"warning",message:u.cannotStartWhy}),t.jsx("p",{className:"text-xs uppercase tracking-wide text-text-muted",children:"ZopNight will run these steps"}),t.jsx(Vt,{steps:u.steps||[]}),i&&t.jsx(Ne,{message:`Failed to start: ${String(i.message||i)}`})]})}function Ze({rec:e}){const{fmtCurrency:s}=G(),n=f.useMemo(()=>{const r=e?.savingsUsd;return!r||Number(r)<=0?null:`${s(Number(r))}/mo`},[e?.savingsUsd,s]);return t.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[t.jsxs("div",{className:"text-sm text-text-secondary",children:["Resource:"," ",t.jsx("span",{className:"font-medium text-text-primary",children:e?.resourceName||e?.resourceUid})]}),n&&t.jsxs("div",{className:"text-sm text-text-secondary",children:["Estimated savings:"," ",t.jsx(O,{content:Ra(e),children:t.jsx("span",{className:"font-medium text-text-primary cursor-help underline decoration-dotted underline-offset-2",children:n})})]})]})}function Pa({workflow:e}){return Le(e.status)?t.jsxs("p",{className:"text-xs text-text-muted",children:["Workflow finished â ",e.status,"."]}):t.jsx("p",{className:"text-xs text-text-muted","data-testid":"workflow-poll-hint",children:"Polling for updatesâ¦"})}function Ne({message:e,variant:s="danger"}){if(s==="warning")return t.jsx("div",{role:"status",className:"rounded-md bg-warning-400/10 px-3 py-2 text-sm text-warning-700",children:e});const{summary:n,advice:r,raw:a,transient:i}=Ks(e),o=a&&a!==n,l=i?{wrapper:"border-warning-400/30 bg-warning-400/5",title:"text-warning-700"}:{wrapper:"border-danger-400/30 bg-danger-400/5",title:"text-danger-600"};return t.jsxs("div",{role:i?"status":"alert",className:`rounded-md border ${l.wrapper} px-3 py-2.5 text-sm`,children:[t.jsx("div",{className:`font-medium ${l.title}`,children:n}),r&&t.jsx("p",{className:"mt-1 text-xs text-text-secondary leading-relaxed",children:r}),o&&t.jsxs("details",{className:"mt-2 group",children:[t.jsxs("summary",{className:"text-xs text-text-muted cursor-pointer hover:text-text-secondary list-none flex items-center gap-1",children:[t.jsx("svg",{className:"w-3 h-3 transition-transform group-open:rotate-90",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:"2","aria-hidden":!0,children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9 5l7 7-7 7"})}),"Show technical details"]}),t.jsx("pre",{className:"mt-1.5 whitespace-pre-wrap break-words text-[11px] font-mono text-text-muted bg-surface-tertiary/60 rounded p-2",children:a})]})]})}function Ba({readOnly:e,activeJobId:s,workflow:n,preview:r,rec:a,isStarting:i,onClose:o,onRestart:l,viewerEmail:c,cancelMutation:d,approveMutation:u,rejectMutation:m}){if(s){if(n&&Le(n.status)){const h=!e&&a?.status==="open"&&typeof l=="function";return t.jsxs("div",{className:"flex justify-end gap-2",children:[h&&t.jsx(D,{variant:"secondary",size:"md",onClick:l,disabled:i,"data-testid":"remediate-again",children:"Remediate again"}),t.jsx(D,{variant:"primary",size:"md",onClick:o,children:"Close"})]})}return t.jsx(Oa,{readOnly:e,workflow:n,rec:a,viewerEmail:c,cancelMutation:d,approveMutation:u,rejectMutation:m,onClose:o})}return!(r?.canStart&&r?.templateId)?t.jsx("div",{className:"flex flex-wrap justify-end gap-2",children:t.jsx(D,{variant:"secondary",size:"md",onClick:o,children:"Cancel"})}):t.jsxs("div",{className:"flex flex-wrap justify-end gap-2",children:[t.jsx(D,{variant:"secondary",size:"md",onClick:o,disabled:i,children:"Cancel"}),i&&t.jsx(D,{variant:"primary",size:"md",disabled:!0,children:"Startingâ¦"})]})}function Oa({readOnly:e,workflow:s,rec:n,viewerEmail:r,cancelMutation:a,approveMutation:i,rejectMutation:o,onClose:l}){const[c,d]=f.useState(!1),[u,m]=f.useState(""),x=s?.viewerRole||"viewer",h=s?.initiatorEmail||"",p=r&&h&&r===h,y=!e&&x!=="viewer"&&(x==="admin"||p),b=f.useMemo(()=>s?.status!=="awaiting_user"?null:(s?.steps||[]).find(v=>v.status==="awaiting_user"&&v.kind==="approval"),[s]),A=!e&&x==="admin"&&!!b&&!p,N=()=>{X(ee.REMEDIATION_CANCELLED,{rule_id:n?.ruleId}),a.mutate({jobId:s.id})},k=()=>{i.mutate({jobId:s.id,stepId:b.id,stepName:b.name})},j=()=>{u.trim()&&o.mutate({jobId:s.id,stepId:b.id,stepName:b.name,reason:u.trim()},{onSuccess:()=>{d(!1),m("")}})};return t.jsxs("div",{className:"flex flex-col gap-2 w-full",children:[c&&t.jsxs("div",{className:"flex flex-wrap items-center gap-2 w-full",children:[t.jsx("input",{type:"text",value:u,onChange:v=>m(v.target.value),placeholder:"Reason for rejection (required)",className:"flex-1 min-w-[200px] rounded-md border border-border-strong bg-surface-tertiary px-3 py-2 text-sm","data-testid":"reject-reason-input"}),t.jsx(D,{variant:"secondary",size:"md",onClick:()=>{d(!1),m("")},disabled:o.isPending,children:"Back"}),t.jsx(D,{variant:"danger",size:"md",onClick:j,disabled:!u.trim()||o.isPending,children:o.isPending?"Rejectingâ¦":"Confirm reject"})]}),!c&&t.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-2 w-full",children:[y&&t.jsx(D,{variant:"danger",size:"md",onClick:N,disabled:a.isPending,title:"Stop the running workflow. The current step will be marked cancelled.",children:a.isPending?"Stoppingâ¦":"Stop workflow"}),A&&t.jsxs(t.Fragment,{children:[t.jsx(D,{variant:"secondary",size:"md",onClick:()=>d(!0),disabled:i.isPending||o.isPending,children:"Reject"}),t.jsx(D,{variant:"primary",size:"md",onClick:k,disabled:i.isPending||o.isPending,children:i.isPending?"Approvingâ¦":"Approve"})]}),t.jsx(D,{variant:"secondary",size:"md",onClick:l,children:"Close"})]})]})}function Fa({rec:e,disabled:s=!1,disabledReason:n="",readOnly:r=!1}){const[a,i]=f.useState(!1);if(!e||e.status!=="open"||e.remediationKind!=="auto"&&e.remediationKind!=="guided")return null;const o=e.remediationKind==="guided"?"Review & remediate":"Remediate",l=s&&n||"Walk through the remediation workflow";return t.jsxs(t.Fragment,{children:[t.jsx(D,{variant:"primary",size:"compact",disabled:s,onClick:()=>{X(ee.RECOMMENDATION_APPLY_STARTED,{rule_id:e.ruleId,action_type:e.remediationKind}),X(ee.REMEDIATION_WIZARD_OPENED,{rule_id:e.ruleId,mode:e.remediationKind}),i(!0)},title:l,children:o}),t.jsx(Ma,{open:a,onClose:()=>i(!1),rec:e,readOnly:r})]})}
3function ye(e){return!!yt(e)||String(e?.ruleId??"").startsWith("WATCH:")}function yt(e){const s=e?.thresholdSnapshot;if(!s)return null;if(typeof s=="object")return s;if(typeof s=="string")try{return JSON.parse(s)}catch{return null}return null}const Ua={ec2:"EC2 instances",rds:"RDS databases","rds-cluster":"RDS clusters","ecs-service":"ECS services","ecs-cluster":"ECS clusters",lambda:"Lambda functions","ebs-volume":"EBS volumes","ebs-snapshot":"EBS snapshots",opensearch:"OpenSearch domains","s3-bucket":"S3 buckets",elb:"load balancers"},za={aws:"AWS",gcp:"Google Cloud",azure:"Azure"};function Yt(e){return za[e]??e}function bt(e,s=!1){const n=e.filter(Boolean);if(n.length<=1)return n[0]??"";const r=s?"or":"and";return`${n.slice(0,-1).join(", ")} ${r} ${n[n.length-1]}`}function Te(e,s,n){if(!(!e||typeof e!="object")){if(Array.isArray(e.all)){e.all.forEach(r=>Te(r,s,n));return}if(Array.isArray(e.any)){e.any.forEach(r=>Te(r,s,n));return}if(e.not){Te(e.not,!s,n);return}e.attr&&n.push({...e,negated:s})}}function Wa(e){const s=(e??[]).map(n=>Ua[n]??`${n} resources`);return bt(s,!0)||"resources"}function Ka(e){const s=e.negated,n=bt(e.values??[],!0);switch(e.attr){case"res.region":return e.op==="neq"?s?`in the ${n} region`:`outside the ${n} region`:s?`outside the ${n} region`:`in the ${n} region`;case"res.provider":return s?`not on ${Yt((e.values??[])[0])}`:`on ${Yt((e.values??[])[0])}`;case"res.status":return s?`that are not ${n}`:`that are ${n}`;case"res.name":return e.op==="contains"?s?`whose name doesn't contain "${(e.values??[])[0]}"`:`whose name contains "${(e.values??[])[0]}"`:s?`not named "${n}"`:`named "${n}"`;default:if(!e.attr?.startsWith("tag."))return null}const r=e.attr.slice(4);return e.op==="exists"?s?`without a "${r}" tag`:`with a "${r}" tag`:e.op==="contains"?`whose "${r}" tag contains "${(e.values??[])[0]}"`:e.op==="neq"?s?`tagged ${r}=${n}`:`not tagged ${r}=${n}`:s?`not tagged ${r}=${n}`:`tagged ${r}=${n}`}function Ha(e){if(!e||typeof e=="object"&&!e.all&&!e.any&&!e.not&&!e.attr)return"any resource in your account";const n=[];Te(e,!1,n);const r=n.find(l=>l.attr==="res.type"),a=r?Wa(r.values):"resources",i=Array.isArray(e.any),o=n.filter(l=>l!==r).map(Ka).filter(Boolean);return o.length?`${a} ${bt(o,i)}`:a}function qa(e){const s=yt(e);return s?Ha(s.scope?.selector):null}function Hs(e){return e?e.remediationKind==="auto"||e.remediationKind==="guided":!1}function Va(e){return(e?.category==="schedule"||ye(e))&&e?.suggestedSchedule!=null}const Ga=new Set(["RC-093","RC-015","RC-110","RC-213"]);function Za(e){return e?.category==="schedule"&&e?.suggestedSchedule==null&&Ga.has(e?.ruleId)}const Ya=7,Qa=24,Ja=.5;function Qt(e,s){if(!Array.isArray(e)||e.length!==Ya)return null;const n=[];for(const r of e){if(!Array.isArray(r)||r.length!==Qa)return null;n.push(r.map(a=>s(Number(a)||0)))}return n}function Oe(e,s){const n=e?.suggestedSchedule??e?.evidence?.suggestedSchedule,r=Qt(n?.activeSlots,o=>o>0);if(r){const o=n.idlePercentage,l=n.timezone||"",c=s?Pt(r,l,s):{grid:r,slotMinutes:60,timezone:l};return{grid:c.grid,slotMinutes:c.slotMinutes,source:"proposed",timezone:c.timezone,idlePct:typeof o=="number"&&o>=0&&o<=1?Math.round(o*100):null}}const a=e?.scheduleHeatmap??e?.evidence?.scheduleHeatmap,i=Qt(a?.slots,o=>o>=Ja);if(i){const o=a.timezone||"",l=s?Pt(i,o,s):{grid:i,slotMinutes:60,timezone:o};return{grid:l.grid,slotMinutes:l.slotMinutes,source:"observed",timezone:l.timezone,idlePct:null}}return null}function Xa(){const e=Is(),s=Er(),n=Nr();return{apply:({rec:a,name:i,description:o,timezone:l,crons:c})=>{s.mutate({name:i,description:o,timezone:l,crons:c,attachResource:{resourceUid:a.resourceUid,resourceName:a.resourceName||"",resourceType:a.resourceType||"",provider:a.provider||"",cloudAccountId:a.cloudAccountId||"",region:a.region||""}},{onSuccess:()=>{n.mutate({id:a.id,status:"applied",source:ye(a)?"custom":void 0},{onSuccess:()=>e("/schedules"),onError:()=>{xe.error("Schedule created, but the recommendation could not be marked applied."),e("/schedules")}})}})},isPending:s.isPending||n.isPending,error:s.error,isError:s.isError,reset:s.reset}}function ei({rec:e,disabled:s=!1,disabledReason:n="",readOnly:r=!1}){const[a,i]=f.useState(!1),{apply:o,isPending:l,error:c,isError:d,reset:u}=Xa(),m=f.useId(),{timezone:x}=f.useContext(Se),h=()=>{i(!1),u()};if(!e||e.status!=="open")return null;const p=c?.message||"",y=d&&/already exists|duplicate|conflict/i.test(p),b=e.suggestedSchedule,A=Oe(e,x),N=A?.source==="proposed"&&A.timezone?_r(A.grid,A.slotMinutes??60):[],k=b?.startCron&&b?.stopCron?[{cronExpression:b.startCron,action:"start"},{cronExpression:b.stopCron,action:"stop"}]:null,j=N.length>0||k!==null,v=b?.idlePercentage,L=A?.idlePct??(typeof v=="number"&&v>=0&&v<=1?Math.round(v*100):null),U={name:`${e.resourceName||e.resourceUid||""} off-hours`.trim(),description:e.title?`Suggested by recommendation "${e.title}"`:e.resourceName?`Suggested off-hours schedule for ${e.resourceName}`:"Suggested off-hours schedule",timezone:N.length>0?A.timezone:b?.timezone||"UTC",crons:N.length>0?N:k??[{cronExpression:"",action:"stop"}]},Z=w=>{r||(X(ee.RECOMMENDATION_SCHEDULED,{rule_id:e.ruleId}),o({rec:e,...w}))};return t.jsxs(t.Fragment,{children:[t.jsx(D,{variant:"primary",size:"compact",disabled:s,onClick:()=>i(!0),title:s&&n?n:"Review and create an off-hours schedule for this resource",children:"Review & remediate"}),a&&t.jsx(be,{open:a,onClose:h,wide:!0,title:`Schedule off-hours: ${e.resourceName||e.resourceUid}`,footer:t.jsxs("div",{className:"flex justify-end gap-2",children:[t.jsx(D,{variant:"secondary",size:"md",onClick:h,disabled:l,children:r?"Close"
3:"Cancel"}),t.jsx(D,{variant:"primary",size:"md",type:"submit",form:m,disabled:l||r,title:r?"Read-only â staff can't create schedules on a customer's behalf":void 0,children:l?"Creatingâ¦":"Create schedule"})]}),children:t.jsxs("div",{className:"space-y-4",children:[r&&t.jsxs("div",{className:"rounded-lg border border-info-400/30 bg-info-400/10 p-3 text-sm text-info-700",children:[t.jsx("p",{className:"font-medium",children:"View only"}),t.jsx("p",{children:"This is ZopNight's internal view of the recommended schedule. The customer applies it from their own account â staff can review the schedule and steps here but can't create it."})]}),j?t.jsxs("div",{className:"rounded-lg border border-border-strong bg-surface-tertiary p-3 text-sm text-text-secondary",children:[t.jsx("p",{className:"font-medium text-text-primary",children:"Recommended off-hours schedule"}),t.jsxs("p",{className:"text-warning-600",children:[L!==null&&t.jsxs(t.Fragment,{children:["This resource is idle ~",L,"% of the week. "]}),"The schedule below is pre-filled from its usage; adjust if needed before creating."]})]}):t.jsxs("div",{className:"rounded-lg border border-border-strong bg-surface-tertiary p-3 text-sm text-text-secondary",children:[t.jsx("p",{className:"font-medium text-text-primary",children:"Create an off-hours schedule"}),t.jsx("p",{children:"Set the hours this resource should run, then create the schedule."})]}),t.jsxs("div",{className:"flex items-center gap-2 rounded-lg border border-border-strong bg-surface-tertiary px-3 py-2",children:[t.jsx(qn,{provider:e.provider,className:"h-4 w-4 shrink-0"}),t.jsx("span",{className:"text-sm font-medium text-text-primary truncate",children:e.resourceName||e.resourceUid}),e.resourceType&&t.jsx("span",{className:"text-xs text-text-muted shrink-0",children:e.resourceType}),t.jsx("span",{className:"ml-auto text-xs text-text-muted whitespace-nowrap",children:r?"attached when the customer creates it":"attached when created"})]}),d&&t.jsxs("div",{role:"alert",className:"rounded-lg border border-danger-400/40 bg-danger-400/10 p-3 text-sm text-danger-700",children:[t.jsx("p",{className:"font-medium",children:"Couldnât create the schedule"}),t.jsx("p",{children:p||"Something went wrong. Please try again."}),y&&t.jsxs("p",{className:"mt-1",children:["A schedule with this name already exists â change the ",t.jsx("strong",{children:"Name"})," above and try again."]})]}),t.jsx(Rr,{defaultValues:U,onSubmit:Z,formId:m})]})})]})}function Jt(e){return String(e||"").toLowerCase().replace(/[\s_]+/g,"-")}function ti({rows:e,provider:s,resourceType:n,feature:r}){const a={gated:!1,reason:""};if(!s||!r)return a;const i=Vn(e,String(s).toLowerCase(),["zopnight"]),o=Jt(n),l=i.find(h=>h.feature===r&&Jt(h.resourceType)===o);if(!l)return a;const c=Array.isArray(l.perms)?l.perms.filter(h=>h.status==="denied"||h.status==="partial").map(h=>h.permission):[];if(l.status!=="needs_attention"&&c.length===0)return a;const u=(c.length?[...new Set(c)].sort():Array.isArray(l.missingPerms)?l.missingPerms:[]).join(", "),m=l.primaryRole;return{gated:!0,reason:m?`ZopNight can't run this yet â grant ${m} on this account to enable it`+(u?` (missing: ${u}).`:"."):"ZopNight is missing the cloud permission to run this"+(u?` (missing: ${u}).`:".")}}function si({cloudAccountId:e,provider:s,resourceType:n,feature:r="remediation"}){const{data:a,isLoading:i}=Tr(e);return f.useMemo(()=>!e||i?{gated:!1,reason:""}:ti({rows:a?.permissions??[],provider:s,resourceType:n,feature:r}),[e,i,a,s,n,r])}function qs(e){switch(e){case"azure":return"Open in Azure Portal";case"gcp":return"Open in GCP Console";default:return"Open in AWS Console"}}function ni({rec:e,provider:s,disabled:n=!1,disabledReason:r=""}){if(!e||!ri(e.consoleUrl)||e.status&&e.status!=="open")return null;const a=qs(s),i=n&&r||"Open this resource in the cloud console",o=()=>{window.open(e.consoleUrl,"_blank","noopener,noreferrer")};return t.jsx(D,{variant:"primary",size:"compact",disabled:n,onClick:o,title:i,children:a})}function ri(e){if(typeof e!="string"||e==="")return!1;let s;try{s=new URL(e)}catch{return!1}return s.protocol==="http:"||s.protocol==="https:"}function ai({open:e}){return t.jsx("svg",{className:`w-3.5 h-3.5 text-text-muted shrink-0 transition-transform ${e?"rotate-180":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,"aria-hidden":"true",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 8.25l-7.5 7.5-7.5-7.5"})})}const ii="flex items-center justify-between gap-3 w-full px-4 py-2.5 bg-surface-tertiary/50";function V({title:e,meta:s,bodyClassName:n="px-4 py-3",testId:r,collapsible:a=!1,defaultOpen:i=!0,titleAdornment:o,headerAction:l,children:c}){const[d,u]=f.useState(i),m=f.useId(),x=!a||d,h=x?"border-b border-border-strong/40":"",p=t.jsxs("span",{className:"flex items-center min-w-0",children:[t.jsx("span",{className:"text-xs font-medium text-text-muted uppercase tracking-wider truncate",children:e}),!a&&o?t.jsx("span",{className:"shrink-0",children:o}):null]});return t.jsxs("div",{"data-testid":r,className:"border border-border-strong/60 rounded-lg overflow-hidden",children:[a?t.jsxs("div",{className:`flex items-stretch bg-surface-tertiary/50 ${h}`,children:[t.jsxs("button",{type:"button",onClick:()=>u(y=>!y),"aria-expanded":d,"aria-controls":m,className:"flex items-center justify-between gap-3 flex-1 min-w-0 px-4 py-2.5 text-left hover:bg-surface-tertiary/70 transition-colors",children:[p,t.jsxs("span",{className:"flex items-center gap-2 shrink-0",children:[s?t.jsx("span",{className:"text-xs text-text-muted",children:s}):null,t.jsx(ai,{open:d})]})]}),l?t.jsx("span",{className:"flex items-center shrink-0 pl-2 pr-4",children:l}):null]}):t.jsxs("div",{className:`${ii} ${h}`,children:[p,t.jsxs("span",{className:"flex items-center gap-2 shrink-0",children:[s?t.jsx("span",{className:"text-xs text-text-muted",children:s}):null,l]})]}),x&&t.jsx("div",{id:m,className:n,children:c})]})}const oi=730,li=[{key:"onDemand",label:"On-Demand",baseline:!0},{key:"ri1yrNoUpfront",label:"Reserved Instance 1-year (No Upfront)"},{key:"ri1yrPartial",label:"Reserved Instance 1-year (Partial Upfront)"},{key:"ri1yrAllUp",label:"Reserved Instance 1-year (All Upfront)"},{key:"ri3yrNoUpfront",label:"Reserved Instance 3-year (No Upfront)"},{key:"ri3yrPartial",label:"Reserved Instance 3-year (Partial Upfront)"},{key:"ri3yrAllUp",label:"Reserved Instance 3-year (All Upfront)"},{key:"sp1yrCompute",label:"Savings Plan 1-year (Compute)"},{key:"sp1yrEc2Inst",label:"Savings Plan 1-year (EC2 Instance)"},{key:"sp3yrCompute",label:"Savings Plan 3-year (Compute)"},{key:"sp3yrEc2Inst",label:"Savings Plan 3-year (EC2 Instance)"},{key:"spot",label:"Spot"}],ci=[{key:"onDemand",label:"On-Demand (Pay-As-You-Go)",baseline:!0},{key:"ri1yrNoUpfront",label:"Reservation 1-year"},{key:"ri3yrNoUpfront",label:"Reservation 3-year"},{key:"sp1yrCompute",label:"Savings Plan 1-year (Compute)"},{key:"sp3yrCompute",label:"Savings Plan 3-year (Compute)"},{key:"spot",label:"Spot"}],di=[{key:"onDemand",label:"On-Demand",baseline:!0},{key:"ri1yrNoUpfront",label:"Committed Use Discount 1-year"},{key:"ri3yrNoUpfront",label:"Committed Use Discount 3-year"},{key:"spot",label:"Spot (Preemptible)"}];function ui(e){switch((e||"").toLowerCase()){case"azure":return ci;case"gcp":return di;default:return li}}function mi(e,s){const n=e?.[s];return typeof n=="number"&&n>0}function xi(e){return e*oi}function pi(e,s){return!e||!s||e>=s?null:(s-e)/s*100}function hi({recommendation:e,provider:s}){const{fmtCurrency:n}=G(),r=e?.tierRates,a=r?.onDemand;if(!a||a<=0)return null;const o=ui(s??e?.provider).filter(l=>l.baseline||mi(r,l.key));return o.filter(l=>!l.baseline).length===0?null:t.jsxs(V,{title:"Commitment Tier Comparison",children:[t.jsxs("table",{className:"w-full",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-border-strong/40",children:[t.jsx("th",{scope:"col",className:"py-2 text-left text-xs font-medium text-text-muted uppercase tracking-wider",children:"Tier"}),t.jsx("th",{scope:"col",className:"py-2 text-right text-xs font-medium text-text-muted uppercase tracking-wider",children:"Hourly"}),t.jsx("th",{scope:"col",className:"py-2 text-right text-xs font-medium text-text-muted uppercase tracking-wider",children:"Monthly"}),t.jsx("th",{scope:"col",className:"py-2 text-right text-xs font-medium text-text-muted uppercase tracking-wider",children:"Savings vs On-Demand"})]})}
3),t.jsx("tbody",{children:o.map(l=>{const c=r?.[l.key]??0,d=xi(c),u=l.baseline?null:pi(c,a);return t.jsxs("tr",{className:"border-b border-border-strong/40 last:border-0",children:[t.jsx("td",{className:`py-2 text-sm ${l.baseline?"font-semibold text-text-primary":"text-text-secondary"}`,children:l.label}),t.jsx("td",{className:"py-2 text-sm tabular-nums text-right text-text-primary",children:n(c,{maximumFractionDigits:4})}),t.jsx("td",{className:"py-2 text-sm tabular-nums text-right text-text-primary",children:n(d)}),t.jsx("td",{className:"py-2 text-sm tabular-nums text-right",children:l.baseline?t.jsx("span",{className:"text-text-muted italic",children:"Baseline"}):u===null?t.jsx("span",{className:"text-text-muted",children:"â"}):t.jsxs("span",{className:"text-success-600 font-medium",children:[u.toFixed(1),"%"]})})]},l.key)})})]}),t.jsx("p",{className:"mt-3 text-xs text-text-muted",children:"Rates from the cloud provider's public catalog. The headline monthly savings on this recommendation is derived from the same source so the table and the headline stay in sync."})]})}async function fi(e,s){if(!s)return null;const n=await e.fetchQuery({queryKey:[...Q.resources.all,"region",s],queryFn:()=>F.get(`/resources/by-uids?uids=${Ir([s])}`),staleTime:6e4});return(Array.isArray(n)?n:n?.items??[])[0]?.region??null}function Vs(){const e=se();return f.useCallback(s=>fi(e,s),[e])}function Ye(e){return e==="idle"||e==="orphan"?"delete":e==="schedule"||e==="performance"?"stop":"modify"}function gi({label:e,icon:s,children:n,placement:r="bottom-end",widthClass:a="w-[min(26rem,calc(100vw-2rem))]",triggerClassName:i=""}){const[o,l]=f.useState(!1),c=f.useId(),{refs:d,floatingStyles:u,context:m}=Gn({open:o,onOpenChange:l,placement:r,whileElementsMounted:Zn,middleware:[Yn(6),Qn(),Jn({padding:8})]}),x=Xn(m),h=er(m),p=tr(m,{role:"dialog"}),{getReferenceProps:y,getFloatingProps:b}=sr([x,h,p]);return t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",ref:d.setReference,"aria-label":e,"aria-expanded":o,"aria-controls":o?c:void 0,className:`inline-flex items-center justify-center rounded-full text-text-muted hover:text-text-secondary transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40 ${i}`,...y(),children:s}),o&&t.jsx(nr,{children:t.jsx("div",{id:c,ref:d.setFloating,style:u,"aria-label":e,...b(),className:`z-[9999] rounded-xl border border-border-strong bg-surface-elevated shadow-xl p-3 text-left normal-case tracking-normal ${a}`,children:n})})]})}const yi=10;function bi(e){return e?.known?e.days>yi?`Monthly figures, measured ${e.label} â ${e.days} days ago, the newest billing day we have for this resource.`:`Monthly figures, measured ${e.label}.`:e?.modelled?"Monthly figures modelled from list price â no billing day behind them.":"Monthly figures. We do not have a measurement date for these."}const Xt={actual:`${Mr} â from your cloud billing for this resource`,calculated:`${Lr} â we have no billing line matched to this resource, so this is modelled from public list price à uptime`};function ji(e){const s=e?.currentCostSource;return Object.hasOwn(Xt,s)?Xt[s]:"Estimated monthly cost for this resource"}const R={title:"text-xl font-semibold text-text-primary leading-snug text-balance",section:"text-xs font-medium text-text-muted uppercase tracking-wider",label:"text-xs font-medium text-text-muted uppercase tracking-wider",body:"text-sm text-text-primary leading-relaxed",bodyMuted:"text-sm text-text-secondary leading-relaxed",caption:"text-xs text-text-muted",captionStrong:"text-xs font-medium text-text-secondary",numericMuted:"text-xs tabular-nums text-text-muted",figure:"text-lg font-semibold tabular-nums leading-none"},rt={"per-hour":{qty:"h",rate:"/hr",tight:!0},"per-GB-hour":{qty:"GB-hr",rate:"/GB-hr",tight:!1},"per-GB-month":{qty:"GB-mo",rate:"/GB-mo",tight:!1},"per-IOPS-hour":{qty:"IOPS-hr",rate:"/IOPS-hr",tight:!1}},vi=Object.fromEntries(Object.keys(rt).map(e=>[e.toLowerCase(),e]));function Gs(e){return!e||typeof e!="string"?null:rt[e]??rt[vi[e.toLowerCase()]]??{qty:e,rate:`/${e}`,tight:!1}}const ke=e=>typeof e=="number"&&Number.isFinite(e);function Zs(e){return e?ke(e.rate)&&ke(e.quantity)&&e.quantity>0&&!!Gs(e.unit):!1}const Ni=new Intl.NumberFormat(void 0,{maximumFractionDigits:3});function wi(e){return Ni.format(e)}const es=6,ts=2;function ki(e,s){if(!ke(e)||!ke(s))return ts;const n=e*s;for(let r=ts;r<=es;r++)if(Math.abs(Number(e.toFixed(r))*s-n)<.005)return r;return es}
3function Si(e,s){if(!Zs(e))return null;const n=Gs(e.unit),r=ki(e.rate,e.quantity),a=`${wi(e.quantity)}${n.tight?"":" "}${n.qty}`,i=s(e.rate,{minimumFractionDigits:r,maximumFractionDigits:r});return`${a} à ${i}${n.rate}`}const Ci=.005;function _i(e){if(!Zs(e))return null;const s=e.amountUsd;if(!ke(s))return"â";const n=e.rate*e.quantity;return Math.abs(n-s)<=Ci?"=":"â"}function Ri(e){return/^[aeiou]/i.test(e)?"an":"a"}function Qe({label:e,value:s,credit:n,total:r}){const{fmtCurrency:a}=G(),i=r?"border-t border-dashed border-border-strong/70":"",o=`py-2 text-sm ${r?"font-semibold text-text-primary":n?"text-success-600":"text-text-secondary"}`,l=`py-2 tabular-nums text-right whitespace-nowrap ${r?"text-base font-bold text-text-primary":"text-sm font-semibold"} ${n?"text-success-600":r?"":"text-text-primary"}`;return t.jsxs("tr",{className:i,children:[t.jsx("td",{className:o,children:e}),t.jsxs("td",{className:l,children:[n?t.jsx("span",{"aria-hidden":"true",children:"â"}):null,a(s)]})]})}function Ys({snapshot:e,className:s=""}){return t.jsx("p",{className:`text-xs leading-tight text-text-muted ${s}`,children:e.stale?e.label?t.jsxs(t.Fragment,{children:[`Monthly savings estimated ${e.label}.`," ",t.jsx(Kn,{to:"/cost-reports",className:"text-primary-600 hover:underline font-medium",children:"See cost reports"})," ","for what this resource costs today."]}):"Monthly savings from an earlier measurement.":bi(e.measurement)})}function Ai({rec:e}){return Number(e?.savingsUsd??0)>0?t.jsxs("div",{className:"px-1 flex flex-col gap-0.5",children:[t.jsx(Ys,{snapshot:Qs(e)}),t.jsx("p",{className:"text-xs leading-tight text-text-muted",children:"Savings shown are an estimate based on this resource's average usage â the actual reduction on your cloud bill may differ."})]}):null}function Ei({label:e,savings:s,annual:n,snapshot:r}){const{fmtCurrency:a}=G();return t.jsxs("div",{className:"px-4 py-2.5 border-t border-border-strong/40",children:[t.jsxs("div",{className:"flex items-end justify-between gap-3 flex-wrap",children:[t.jsx("span",{className:"text-sm font-semibold text-text-primary",children:e}),t.jsxs("div",{className:"flex flex-col items-end min-w-0",children:[t.jsxs("span",{className:"flex items-baseline gap-1 text-success-600",children:[t.jsx("span",{className:`${R.figure} whitespace-nowrap`,children:a(s)}),t.jsx("span",{className:"text-xs font-medium",children:"/mo"})]}),n!==null&&t.jsxs("span",{className:"text-xs leading-tight text-success-600",children:[t.jsx("span",{className:"font-medium tabular-nums",children:a(n)}),t.jsx("span",{children:"/yr"})]})]})]}),t.jsx(Ys,{snapshot:r,className:"mt-0.5"})]})}function Ti({component:e}){const{fmtCurrency:s}=G(),n=Si(e,s),r=_i(e);return t.jsxs("tr",{children:[t.jsx("td",{className:"py-1 pl-4 text-xs text-text-secondary align-top",children:t.jsxs("span",{className:"flex flex-wrap items-baseline gap-x-2",children:[t.jsx("span",{children:e?.label}),n&&t.jsx("span",{className:"tabular-nums text-text-muted",children:n})]})}),t.jsxs("td",{className:"py-1 tabular-nums text-right text-xs text-text-secondary whitespace-nowrap align-top",children:[n&&t.jsxs("span",{className:"text-text-muted",children:[r," "]}),s(e?.amountUsd)]})]})}const Ii=7,$i=.01;function Li(e,s){return s<=e+$i}function Qs(e){const s=e?.lastReevaluatedAt||e?.updatedAt||e?.generatedAt||null,n=le(s),r=ct(s);return{label:n,stale:n===null||r===null||r>Ii,measurement:Mi(e)}}function Mi(e){const s=e?.costMeasuredThrough||null,n=le(s),r=ct(s);return{label:n,days:r,known:n!==null&&r!==null,modelled:e?.currentCostSource==="calculated"}}const Je={open:{current:"Current monthly cost",reduction:"Reduction from this recommendation",total:"New monthly total",savings:"You save"},verified:{current:"Monthly cost before the change",reduction:"Reduction from this change",total:"Monthly cost now",savings:"You saved"},estimated:{current:"Monthly cost before the change",reduction:"Reduction from this change",total:"Monthly cost now",savings:"Estimated saving"}};function Di({rec:e,isOpen:s,category:n,hasCost:r,option:a}){if(!r)return t.jsxs("p",{className:"px-4 py-3 text-sm text-text-secondary",children:["No direct cost impact. This is ",Ri(n||"governance")," ",n||"governance"," recommendation."]});const i=e.currentCostUsd??0,o=a?a.costUsd??null:e.optimizedCostUsd??null,l=(a?a.savingsUsd:e.savingsUsd)??0,c=typeof e.annualSavingsUsd=="number"?e.annualSavingsUsd:null,d=a&&!a.recommended?null:c,u=Qs(e),m=s?Je.open:dt(e,s)==="Saved"?Je.verified:Je.estimated,x=i>0&&!u.stale&&Li(i,l),h=a&&!a.recommended?[]:Array.isArray(e.savingsBreakdown)?e.savingsBreakdown:[];return t.jsxs("div",{className:"flex flex-col",children:[x&&t.jsx("div",{className:"px-4 py-1",children:t.jsxs("table",{className:"w-full",children:[t.jsx("caption",{className:"sr-only",children:"This resource's monthly cost, what this recommendation takes off it, and the total that leaves"}),t.jsxs("tbody",{children:[t.jsx(Qe,{label:m.current,value:i}),t.jsx(Qe,{label:m.reduction,value:l,credit:!0}),h.map((p,y)=>t.jsx(Ti,{component:p},`${y}-${p?.label}`)),o!==null&&t.jsx(Qe,{label:m.total,value:o,total:!0})]})]})}),t.jsx(Ei,{label:m.savings,savings:l,annual:d,snapshot:u})]})}const Pi={delete:"delete this resource",stop:"stop this resource",pause:"pause this resource",resize:"resize this resource",schedule:"put this resource on a schedule",configure:"apply this change"},Bi="apply this recommendation";function Js(e){return Pi[e]||Bi}function Oi({recoverable:e,lever:s}){const n=Js(s);return e?t.jsx("span",{className:"text-[11px] text-text-muted",children:`Stops when you ${n}`}):t.jsx("span",{className:"text-[11px] font-medium text-warning-600",children:`Keeps billing after you ${n}`})}function Fi({child:e,lever:s}){const{fmtCurrency:n}=G();return t.jsxs("tr",{className:"border-t border-border-strong/40",children:[t.jsx("td",{className:"py-2 pr-3",children:t.jsxs("div",{className:"flex flex-col gap-0.5 min-w-0",children:[t.jsx("span",{className:"text-sm text-text-primary break-words",children:e?.resourceName||e?.resourceUid}),t.jsxs("span",{className:"text-[11px] text-text-muted break-words",children:[e?.resourceType,e?.resourceType?" · ":"",t.jsx(Oi,{recoverable:!!e?.recoverable,lever:s})]})]})}),t.jsx("td",{className:"py-2 text-right tabular-nums text-sm font-semibold text-text-primary whitespace-nowrap",children:n(e?.monthlyCostUsd??null)})]})}function Ui(e){return(e?.children??[]).length>0}const zi=t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[t.jsx("circle",{cx:"12",cy:"12",r:"10"}),t.jsx("line",{x1:"12",y1:"16",x2:"12",y2:"11"}),t.jsx("line",{x1:"12",y1:"8",x2:"12.01",y2:"8"})]});function Wi({breakdown:e,lever:s}){const{fmtCurrency:n}=G(),r=e?.children??[],a=e?.childTotalUsd??null,i=e?.recoverableUsd??0,o=e?.
3nonRecoverableUsd??0,l=Js(s);return t.jsxs("div",{"data-testid":"rec-child-cost-breakdown",className:"flex flex-col gap-2.5",children:[t.jsx("p",{className:R.section,children:"Attached resources"}),t.jsx("p",{className:R.caption,children:"Billed separately from this resource's own cost."}),t.jsxs("table",{className:"w-full",children:[t.jsx("caption",{className:"sr-only",children:"Resources attached to this one and what each bills per month"}),t.jsx("thead",{className:"sr-only",children:t.jsxs("tr",{children:[t.jsx("th",{scope:"col",children:"Attached resource"}),t.jsx("th",{scope:"col",children:"Monthly cost"})]})}),t.jsx("tbody",{children:r.map((c,d)=>t.jsx(Fi,{child:c,lever:s},c?.resourceUid||`child-${d}`))}),t.jsx("tfoot",{children:t.jsxs("tr",{className:"border-t border-border-strong",children:[t.jsx("th",{scope:"row",className:`py-2 pr-3 text-left ${R.captionStrong}`,children:"Total"}),t.jsxs("td",{className:"py-2 text-right whitespace-nowrap",children:[t.jsx("span",{className:"text-sm font-semibold tabular-nums text-text-primary",children:n(a)}),t.jsx("span",{className:R.caption,children:" /mo"})]})]})})]}),o>0&&t.jsxs("p",{className:"text-xs text-warning-600",children:[t.jsx("span",{className:"font-semibold",children:`${n(o)} /mo keeps billing after you ${l}.`})," ","That is not part of this saving â it has to be deleted or released separately."]}),i>0&&t.jsx("p",{className:R.caption,children:`${n(i)} /mo stops when you ${l}.`})]})}function Ki({breakdown:e,lever:s}){return Ui(e)?t.jsx(gi,{label:"Attached resources billed separately",icon:zi,placement:"bottom-start",triggerClassName:"ml-1.5 align-middle",children:t.jsx(Wi,{breakdown:e,lever:s})}):null}function Hi({rec:e,isOpen:s,category:n,hasCost:r,option:a}){return t.jsx(V,{testId:"rec-monthly-bill",title:s?"Monthly bill":dt(e,s)==="Saved"?"Confirmed change":"Estimated savings",meta:r?ji(e):void 0,bodyClassName:"",titleAdornment:t.jsx(Ki,{breakdown:e?.costBreakdown,lever:e?.lever}),children:t.jsx(Di,{rec:e,isOpen:s,category:n,hasCost:r,option:a})})}const jt=30;function ss(e){return e.toISOString().slice(0,10)}function Xs(e=jt,s=new Date){const n=new Date(s),r=new Date(s);return r.setDate(r.getDate()-e),{from:ss(r),to:ss(n)}}function qi(e,{from:s,to:n,enabled:r=!0}={}){const a=s&&n?{from:s,to:n}:Xs();return ce({queryKey:Q.recommendations.costHistory(e,a.from,a.to),queryFn:()=>F.get("/reports/cost-history",{resource_uid:e,from:a.from,to:a.to}),enabled:!!e&&r,placeholderData:Os,staleTime:300*1e3})}function Vi(e){const s=Array.isArray(e)?e:[];let n=0,r=0,a=0;for(const o of s)o?.costSource==="actual"&&typeof o?.actualCostUsd=="number"?(n+=o.actualCostUsd,a+=1):r+=Number(o?.costUsd)||0;const i=s.map(o=>o?.date).filter(Boolean).sort();return{rows:s,period:i.length?{from:i[0],to:i[i.length-1]}:null,days:s.length,actualDays:a,actualTotal:n,calculatedTotal:r,total:n+r,allActual:s.length>0&&a===s.length}}const Gi=[{days:7,label:"7d"},{days:jt,label:"30d"},{days:90,label:"90d"}];function Zi({rec:e}){const{fmtCurrency:s}=G(),{internal:n}=ut(),[r,a]=f.useState(jt),i=f.useMemo(()=>Xs(r),[r]),{data:o,isLoading:l,isError:c}=qi(e?.resourceUid,{...i,enabled:n}),d=f.useMemo(()=>Vi(o),[o]),[u,m]=f.useState(!1),x=!l,h=!c&&d.days===0;return!n||!e?.resourceUid||!x||h&&!u?null:t.jsxs(V,{testId:"rec-billed-cost",title:"Billed cost",meta:t.jsx("div",{className:"flex items-center gap-1",role:"group","aria-label":"Cost history range",children:Gi.map(p=>t.jsx("button",{type:"button",onClick:()=>{a(p.days),m(!0)},"aria-pressed":r===p.days,className:r===p.days?"rounded px-2 py-0.5 text-xs bg-surface-tertiary text-text-primary":"rounded px-2 py-0.5 text-xs text-text-tertiary hover:text-text-secondary",children:p.label},p.days))}),children:[c&&t.jsx("p",{className:R.body,children:"Cost history is unavailable right now."}),h&&t.jsxs("p",{className:R.body,"data-testid":"rec-billed-cost-empty",children:["No billed cost between ",i.from," and ",i.to,"."]}),!c&&d.days>0&&t.jsxs(t.Fragment,{children:[t.jsxs("p",{className:R.body,children:[t.jsx("strong",{children:s(d.total)})," over ",d.days," ",d.days===1?"day":"days",t.jsxs(t.Fragment,{children:[" ","(",(d.period??i).from," â ",(d.period??i).to,")"]})]}),d.allActual?t.jsx("p",{className:R.caption,children:"From your provider's billing data."}):t.jsxs("p",{className:R.caption,children:[s(d.actualTotal)," from billing data over ",d.actualDays," of"," ",d.days," days; the rest is calculated from rate and uptime and may differ from your invoice."]})]})]})}function Yi(){const e=ce({queryKey:Q.recommendations.bookmarks(),queryFn:()=>F.get("/recommendations/bookmarks"),staleTime:3e5});return f.useMemo(()=>new Set(e.data?.recIds??[]),[e.data])}function Qi(){const e=se();return de({mutationFn:({recId:s,bookmarked:n})=>F.patch(`/recommendations/${s}/bookmark`,{bookmarked:n}),onMutate:async({recId:s,bookmarked:n})=>{await e.cancelQueries({queryKey:Q.recommendations.bookmarks()});const r=e.getQueryData(Q.recommendations.bookmarks());return e.setQueryData(Q.recommendations.bookmarks(),a=>{const i=new Set(a?.recIds??[]);return n?i.add(s):i.delete(s),{recIds:[...i].sort()}}),{previous:r}},onError:(s,n,r)=>
3{r?.previous!==void 0&&e.setQueryData(Q.recommendations.bookmarks(),r.previous),xe.error(s?.message||"Could not update the bookmark.")},onSettled:()=>{e.invalidateQueries({queryKey:Q.recommendations.bookmarks()}),e.invalidateQueries({predicate:s=>s.queryKey[0]==="recommendations"&&s.queryKey.some(n=>n&&typeof n=="object"&&n.bookmarked===!0)})}})}function Ji({rec:e}){const s=Yi(),n=Qi();if(!e?.id)return null;const r=s.has(e.id);return t.jsx("button",{type:"button",onClick:()=>n.mutate({recId:e.id,bookmarked:!r}),disabled:n.isPending,"aria-pressed":r,"aria-label":r?"Remove bookmark":"Bookmark this recommendation",title:r?"Remove bookmark":"Bookmark this recommendation",className:"inline-flex shrink-0 items-center rounded p-1 text-text-tertiary transition-colors hover:text-warning-400 disabled:opacity-50",children:t.jsx("svg",{className:"shrink-0",width:"14",height:"14",viewBox:"0 0 24 24",fill:r?"currentColor":"none",stroke:"currentColor",strokeWidth:1.75,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:t.jsx("path",{d:"M12 2.5l2.9 5.9 6.5.9-4.7 4.6 1.1 6.5-5.8-3-5.8 3 1.1-6.5L2.6 9.3l6.5-.9z"})})})}function Xi(e,s,n){const r=Array.isArray(e?.datapoints)?e.datapoints:[],a=Array.isArray(e?.datapointsMax)?e.datapointsMax:null,i=Array.isArray(e?.datapointsMin)?e.datapointsMin:null;if(!(r.length>0&&a?.length===r.length&&i?.length===r.length))return{showMaxBand:!1,showMinBand:!1};const l=e?.startTs??0,c=e?.granularity||3600,d=n-s*86400,u=[];for(let x=0;x<r.length;x++){const h=l+x*c;h<d||h>n||u.push({value:Number.isFinite(r[x])?r[x]:null,max:Number.isFinite(a[x])?a[x]:null,min:Number.isFinite(i[x])?i[x]:null})}const m=x=>{let h=!1;for(const p of u)if(Number.isFinite(p[x])&&(h=!0,p[x]!==0))return!0;return h?!u.some(p=>Number.isFinite(p.value)&&p.value!==0):!1};return{showMaxBand:m("max"),showMinBand:m("min")}}const eo=14;function je(e,s){const n=e?.length>0?e:s?.metricName?[s]:[],r=new Set,a=[];for(const i of n){const o=i?.metricName;!o||r.has(o)||(r.add(o),a.push(i))}return a}const Me=[];function to(e,s){const n=new Map;for(const r of s)!r?.metricName||n.has(r.metricName)||!Ms(r)||Ie(r)||n.set(r.metricName,{...r,used:!1});for(const r of e){if(!r?.metricName||Ie(r))continue;const a=n.get(r.metricName);n.set(r.metricName,a?{...a,used:!0,threshold:r.threshold??a.threshold,operator:r.operator??a.operator}:{...r,used:!0})}return[...n.values()].sort((r,a)=>{if(r.used!==a.used)return r.used?-1:1;const i=$e[r.metricName]??r.metricName,o=$e[a.metricName]??a.metricName;return i.localeCompare(o)})}function vt(e,s){return je(e.evidenceMetrics,e.evidence).some(r=>Ee(r,s))}function at(e){const s=e?.datapoints?.length??0;if(s===0)return 0;const n=e?.startTs??0;return n?n+(s-1)*(e.granularity||3600):0}function so({open:e,onClose:s,metrics:n,resourceName:r,activityPanel:a,anchorSec:i,timeZone:o}){const[l,c]=f.useState(14),[d,u]=f.useState(null),[m,x]=f.useState({avg:!0,max:!0,min:!0}),h=p=>x(y=>{const b=Object.values(y).filter(Boolean).length;return y[p]&&b===1?y:{...y,[p]:!y[p]}});return e?t.jsx(be,{open:!0,wide:!0,onClose:s,title:r?`All metrics for ${r}`:"All metrics",headerRight:t.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-x-4 gap-y-2 min-w-0",children:[d&&t.jsxs("button",{type:"button",onClick:()=>u(null),className:"inline-flex items-center gap-1 text-[11px] font-medium text-text-muted hover:text-primary-600 transition-colors whitespace-nowrap shrink-0",title:"Clear the drag-selected zoom on all charts",children:[t.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"w-3 h-3 shrink-0","aria-hidden":"true",children:[t.jsx("path",{d:"M3 2v6h6"}),t.jsx("path",{d:"M3 8a9 9 0 1 0 3-5.3"})]}),"Reset zoom"]}),t.jsx("div",{className:"shrink-0",children:t.jsx(pr,{show:m,onToggle:h})}),t.jsx("div",{className:"shrink-0",children:t.jsx(hr,{value:l,zoomed:!!d,onChange:p=>{c(p),u(null)}})})]}),children:n.length===0&&!a?t.jsx("p",{className:"text-sm text-text-secondary px-1 py-4",children:"No metrics available for this resource."}):t.jsxs("div",{className:"grid grid-cols-1 xl:grid-cols-2 gap-4 p-1",children:[a,n.map(p=>t.jsx(xr,{metric:p,rangeDays:l,zoomDomain:d,onZoom:u,broadcastShow:m,anchorSec:i,timeZone:o},`${p.metricName}-${l}`))]})}):null}function en({rec:e,embedded:s=!1}
3){const[n]=f.useState(()=>Math.floor(Date.now()/1e3)),{data:r,isError:a,refetch:i}=Ls(e?.resourceUid?[e.resourceUid]:Me),o=r?.items??Me,l=vt(e,n)||je(e.evidenceMetrics,e.evidence).some(d=>at(d)>0)||o.some(d=>Ms(d)&&at(d)>0);if(a&&!l){const d=t.jsxs("p",{className:"text-sm text-text-secondary",children:["Couldn't load usage metrics for this resource."," ",t.jsx("button",{type:"button",onClick:()=>i(),className:"text-primary-600 hover:underline font-medium",children:"Retry"})]});return s?d:t.jsx(V,{title:"Usage metrics",children:d})}if(!l)return null;const c=t.jsx(tn,{evidenceMetrics:e.evidenceMetrics,evidence:e.evidence,activitySeries:e.activitySeries,resourceUid:e.resourceUid,resourceName:e.resourceName||e.resourceUid,liveOnly:!0,inset:s});return s?c:t.jsx(V,{title:"Usage metrics",children:c})}function tn({evidenceMetrics:e,evidence:s,activitySeries:n,resourceUid:r,resourceName:a,liveOnly:i=!1,inset:o=!1}){const l=f.useMemo(()=>je(e,s),[e,s]),[c]=f.useState(()=>Math.floor(Date.now()/1e3)),{timezone:d}=f.useContext(Se),u=l.some(C=>Ee(C,c)),{data:m,isFetching:x}=Ls(r&&(u||i)?[r]:Me),h=m?.items??Me,p=f.useMemo(()=>to(l,h),[l,h]),[y,b]=f.useState(!1),A=f.useMemo(()=>h.find(Ie)??l.find(Ie)??null,[h,l]),N=cr({resourceUid:r,series:n??A}),{hasActivity:k}=N,j=p.some(C=>Ee(C,c)),v=p.reduce((C,P)=>Math.max(C,at(P)),0),L=j?c:v,U=!j&&v>0;if(!(p.some(C=>Ee(C,L))||k))return null;const w=p[0],M=w?.periodDays>0?w.periodDays:eo,$=dr(w,M,L),g=Ds(w?.metricName,w?.unit),E=[];$?.avg!=null&&E.push(`avg ${Ps($.avg,g)}`),w?.periodDays>0&&E.push(`${w.periodDays}d`);const _=E.join(" · "),T=p.length+(k?1:0),{showMaxBand:W,showMinBand:z}=$?Xi(w,M,L):{showMaxBand:!1,showMinBand:!1},H=["avg",...W?["max"]:[],...z?["min"]:[]],S=H.length>1;return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"space-y-2",children:[t.jsxs("div",{className:"flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1",children:[t.jsx("span",{className:"text-sm font-medium text-text-primary min-w-0 truncate",children:$e[w?.metricName]??w?.metricName??"Recent activity"}),t.jsxs("span",{className:"flex items-center gap-3 shrink-0",children:[_&&t.jsx("span",{className:"text-[11px] text-text-muted tabular-nums",children:_}),S&&t.jsx("span",{className:"flex items-center gap-2","aria-label":`Chart key: ${H.map(C=>He[C].label).join(", ")}`,children:H.map(C=>t.jsxs("span",{className:"inline-flex items-center gap-1 text-[11px] text-text-muted",children:[t.jsx("span",{className:"w-1.5 h-1.5 rounded-full shrink-0",style:{background:He[C].color},"aria-hidden":"true"}),He[C].label]},C))}),x&&t.jsxs("span",{role:"status","aria-live":"polite",className:"inline-flex items-center gap-1 text-[11px] text-text-muted whitespace-nowrap",children:[t.jsx("span",{className:"w-3 h-3 rounded-full border-2 border-text-muted/30 border-t-text-muted animate-spin"}),"Loadingâ¦"]}),t.jsxs("button",{type:"button",onClick:()=>b(!0),className:"inline-flex items-center gap-0.5 text-[11px] font-medium text-primary-600 hover:underline whitespace-nowrap",title:"Chart every metric at once, with the range and series controls",children:["All graphs (",T,")",t.jsx("span",{"aria-hidden":"true",children:"âº"})]})]})]}),t.jsx("div",{children:t.jsx("div",{className:o?"":"-mx-4",children:t.jsx(ur,{evidence:w,hideBorder:!0,hideLabel:!0,hideLegend:!0,rangeDays:M,anchorSec:U?L:void 0,timeZone:d},w?.metricName)})}),U&&t.jsxs("p",{className:"text-[11px] text-warning-600",children:["No recent data â showing history through"," ",new Date(L*1e3).toLocaleDateString(void 0,{month:"short",day:"numeric",year:"numeric"}),", the newest this resource reported."]})]}),t.jsx(so,{open:y,onClose:()=>b(!1),metrics:p,resourceName:a,anchorSec:U?L:void 0,timeZone:d,activityPanel:k?t.jsx(mr,{view:N,timeZone:d}):null})]})}const no="ecr",we=1024**3,ns=2,rs=1024,ro=1024**2;function as(e){return Number.isFinite(e)?e.toLocaleString(void 0,{minimumFractionDigits:ns,maximumFractionDigits:ns}):"â"}function re(e){if(!Number.isFinite(e))return"â";const s=e/we;return s>=rs?`${as(s/rs)} TiB`:s>=1?`${as(s)} GiB`:`${(e/ro).toFixed(0)} MiB`}function J(e){if(e==null||e==="")return null;const s=Number(e);return Number.isFinite(s)?s:null}const ao=new Set(["true","yes","1"]);function is(e){return e===!0?!0:typeof e=="string"&&ao.has(e.trim().toLowerCase())}function sn(e,s){if(!Number.isFinite(e)||e<0)return{pct:null,totalBytes:null};const n=Number.isFinite(s)&&s>0?s:null,r=n!==null&&e>n?null:n;let a=null;return r!==null&&(a=Math.round(e/r*100),a>=100&&e!==r&&(a=99)),{pct:a,totalBytes:r}}
3function io(e,s){if(!Number.isFinite(e)||e<=0)return null;const n=Number.isFinite(s)&&s>0?s:null,{pct:r,totalBytes:a}=sn(e,n===null?null:n*we);return{prunableBytes:e,prunableGib:e/we,totalGib:a===null?null:a/we,pct:r}}function nn(e){if(e?.resourceType!==no)return null;const s=e?.specs??{};if(!is(s.prunable_refs_resolved))return null;const n=J(s.prunable_image_bytes);if(n===null||n<=0)return null;const r=J(s.prunable_image_count),a=J(s.last_image_pull_time),i={countPhrase:r!==null&&r>0?`${r} image${r===1?"":"s"}`:null,lastPullLabel:a===null?null:le(a*1e3)},o=J(s.prunable_exclusive_bytes);if(is(s.dedup_resolved)&&o!==null&&o>=0){const{pct:d,totalBytes:u}=sn(o,J(s.stored_bytes_deduplicated)??NaN),m=re(o),x=re(n);return{...i,dedup:!0,pct:d,volume:m,total:u===null?null:re(u),summedVolume:x===m?null:x}}const l=io(n,J(s.size_gb)??NaN),c=l?.totalGib==null?null:l.totalGib*we;return{...i,dedup:!1,pct:l?.pct??null,volume:re(n),total:c===null?null:re(c),summedVolume:null}}const oo=t.jsx("svg",{viewBox:"0 0 24 24",fill:"currentColor",className:"w-3.5 h-3.5 shrink-0","aria-hidden":"true",children:t.jsx("path",{d:"M12 2l2.9 6.26 6.85.72-5.12 4.62 1.46 6.73L12 16.9l-6.09 3.43 1.46-6.73L2.25 8.98l6.85-.72L12 2z"})});function lo({option:e,name:s,selected:n,onSelect:r}){const{fmtCurrency:a}=G(),i="py-2.5 px-2 text-sm align-middle";return t.jsxs("tr",{className:n?"bg-primary-600/5":"",children:[t.jsx("td",{className:`${i} w-px`,children:t.jsx("input",{type:"radio",name:s,value:e.id,checked:n,onChange:()=>r(e.id),id:`${s}-${e.id}`,className:"h-4 w-4 accent-primary-600 cursor-pointer"})}),t.jsx("th",{scope:"row",className:`${i} font-normal text-left`,children:t.jsxs("label",{htmlFor:`${s}-${e.id}`,className:"flex items-center gap-1.5 cursor-pointer text-text-primary font-medium",children:[e.recommended&&t.jsx("span",{className:"text-primary-600",children:oo}),t.jsx("span",{className:e.recommended?"text-primary-600":"",children:e.label})]})}),t.jsx("td",{className:`${i} text-text-secondary break-words`,children:e.configuration}),t.jsx("td",{className:`${i} text-right tabular-nums whitespace-nowrap text-text-primary`,children:a(e.costUsd)}),t.jsx("td",{className:`${i} text-right tabular-nums whitespace-nowrap`,children:e.baseline?t.jsx("span",{className:"text-text-muted",children:"Baseline"}):t.jsxs("span",{className:"text-success-600 font-medium",children:[a(e.savingsUsd),e.savingsPct!==null&&` (${e.savingsPct}%)`]})}),t.jsx("td",{className:`${i} text-right text-text-secondary whitespace-nowrap`,children:e.risk})]})}const he="py-1.5 px-2 text-[11px] font-medium uppercase tracking-wider text-text-muted";function co({options:e,selectedId:s,onSelect:n}){const{fmtCurrency:r}=G();if(e.length===0)return null;const a=e.find(l=>l.id===s)??e[e.length-1],i="rec-option",o=e.find(l=>l.baseline);return t.jsxs(V,{testId:"rec-recommendation-options",title:"Recommendation options",bodyClassName:"",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-3 flex-wrap px-4 pt-3 pb-1",children:[t.jsx("span",{className:"text-sm text-text-secondary break-words min-w-0",children:a.baseline?t.jsxs(t.Fragment,{children:["Keep ",a.configuration]}):t.jsxs(t.Fragment,{children:[o?.configuration,t.jsx("span",{"aria-hidden":"true",className:"mx-1.5 text-text-muted",children:"â"}),t.jsx("span",{className:"font-semibold text-text-primary",children:a.configuration})]})}),t.jsxs("span",{className:"text-sm tabular-nums text-text-secondary whitespace-nowrap",children:[r(a.costUsd),t.jsx("span",{className:"text-text-muted",children:"/mo"}),a.savingsUsd>0&&t.jsxs(t.Fragment,{children:[" · ",t.jsxs("span",{className:"text-success-600",children:["saves ",r(a.savingsUsd),"/mo"]})]})]})]}),t.jsx("div",{className:"px-2 pb-2 overflow-x-auto",children:t.jsxs("table",{className:"w-full min-w-[34rem]",children:[t.jsx("caption",{className:"sr-only",children:"Choose a configuration for this resource. Selecting one updates the monthly bill above."}),t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-border-strong/40",children:[t.jsx("th",{scope:"col",className:`${he}
3 w-px`,children:t.jsx("span",{className:"sr-only",children:"Select"})}),t.jsx("th",{scope:"col",className:`${he} text-left`,children:"Option"}),t.jsx("th",{scope:"col",className:`${he} text-left`,children:"Configuration"}),t.jsx("th",{scope:"col",className:`${he} text-right`,children:"Cost /mo"}),t.jsx("th",{scope:"col",className:`${he} text-right`,children:"Est. savings"}),t.jsx("th",{scope:"col",className:`${he} text-right`,children:"Risk"})]})}),t.jsx("tbody",{children:e.map(l=>t.jsx(lo,{option:l,name:i,selected:l.id===a.id,onSelect:n},l.id))})]})})]})}function uo(e,s){return!e||!s?!1:String(s).split(/[.;(]/)[0].trim().replace(/[\s.,;:]+$/,"").toLowerCase()===e.trim().toLowerCase()}function mo(e){const s=[];if(e.change&&s.push({key:"change",iconKey:"change",label:"What changes",body:e.change}),e.reversible){s.push({key:"reversibility",iconKey:e.irreversible?"irreversible":"reversible",label:e.irreversible?"Cannot be undone":"Reversibility",status:e.irreversible?"Permanent":e.verdict==="review"?e.unclassified?"Unknown":"Partly reversible":"Reversible",statusTone:e.irreversible?"danger":e.verdict==="review"?"review":"good",body:e.reversible});const n=s[s.length-1];uo(n.status,n.body)&&(n.status=void 0,n.statusTone=void 0)}return e.after&&s.push({key:"after",iconKey:"after",label:"After you apply",body:e.after}),s}function xo(e){return e&&(e.instance_type||e.instance_class||e.machine_type)||""}const os={delete:{verdict:"review",irreversible:!0,change:"Deletes this resource. It has had no meaningful activity for 14+ days.",reversible:"Deletion is permanent. Snapshot or export its configuration first.",after:"Confirm no scheduled or seasonal job depends on it before deleting."},resize:{verdict:"review",change:"Right-sizes this resource to a smaller tier that stays above observed peak usage.",reversible:"Reversible. Resize back to the current tier at any time.",after:"Best applied in a maintenance window. Watch peak utilisation for 48h and revert if it climbs."},configure:{verdict:"safe",change:"Changes a capacity/configuration setting to match the observed usage pattern.",reversible:"Reversible. Revert the setting at any time.",after:"Monitor throttling/behaviour for 48h after the change."},stop:{verdict:"review",change:"Stops this resource. It has had no meaningful activity for 14+ days.",reversible:"Reversible. Restart it anytime; nothing is deleted.",after:"Confirm no scheduled or seasonal job depends on it before applying."},pause:{verdict:"review",change:"Pauses this service. It has had no meaningful activity for 14+ days.",reversible:"Reversible. Resume it anytime; nothing is deleted.",after:"Confirm no scheduled or seasonal job depends on it before applying."},schedule:{verdict:"safe",change:"Attaches an off-hours schedule that stops it during idle windows and starts it before working hours.",reversible:"Fully reversible. Detach the schedule anytime to return to 24/7.",after:"Nothing is deleted. The first stop happens at the next scheduled off-window."}},po={verdict:"review",change:"Stops or deletes a resource with no meaningful activity for 14+ days.",reversible:"Stopping is reversible (restart anytime). Deletion is permanent. Snapshot first.",after:"Confirm no scheduled or seasonal job depends on it before deleting."};function Nt(e,s){const n=xo(e.specs);switch(s){case"schedule":return{verdict:"safe",change:"Runs 24/7 today. This attaches an off-hours schedule that stops it when idle and starts it before working hours.",reversible:"Fully reversible. Detach the schedule anytime to return to 24/7.",after:"Nothing is deleted. The first stop happens at the next scheduled off-window."};case"rightsizing":return{verdict:"safe",change:n?`Right-sizes ${n} to a smaller tier that stays above observed peak usage.`:"Moves to a smaller tier that stays above observed peak usage.",reversible:"Reversible. Resize back to the current tier at any time.",after:"Best applied in a maintenance window. Watch peak utilisation for 48h and revert if it climbs."};case"idle":return Object.hasOwn(os,e.lever??"")?os[e.lever]:po;case"orphan":return{verdict:"review",irreversible:!0,change:"Deletes a resource no live workload references (for example an unattached disk or reserved IP).",reversible:"Deleti
3on is permanent. Export the configuration or take a snapshot before applying.",after:"Verify nothing has referenced it in the last 30 days."};default:return{verdict:"review",unclassified:!0,change:"Applies the recommended optimisation described below.",reversible:"Not classified for this rule. Check whether the change can be undone before you apply it.",after:"Review the steps below before applying."}}}function ho(e){const s=je(e.evidenceMetrics,e.evidence),n=s.find(r=>r.datapoints?.length)||s[0];if(n&&n.periodDays){const r=Ds(n.metricName,n.unit);return`${$e[n.metricName]??n.metricName} averaged ${Ps(n.average??0,r)} over ${n.periodDays} days of data.`}return"Based on the resource's recent usage history."}const fo={1:"lg:grid-cols-1",2:"lg:grid-cols-2",3:"lg:grid-cols-3",4:"lg:grid-cols-2",5:"lg:grid-cols-3",6:"lg:grid-cols-3"};function go({icon:e,label:s,status:n,statusTone:r,children:a}){const i=r==="danger"?"text-danger-600":r==="review"?"text-warning-600":"text-success-600";return t.jsxs("div",{className:"min-w-0 space-y-1",children:[t.jsxs("p",{className:"flex items-center gap-2 flex-wrap",children:[t.jsx("span",{className:"shrink-0 text-text-muted",children:e}),t.jsx("span",{className:R.label,children:s}),n&&t.jsx("span",{className:`text-xs font-semibold ${i}`,children:n})]}),t.jsx("p",{className:R.bodyMuted,children:a})]})}const yo={change:t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[t.jsx("polyline",{points:"17 1 21 5 17 9"}),t.jsx("path",{d:"M3 11V9a4 4 0 0 1 4-4h14"}),t.jsx("polyline",{points:"7 23 3 19 7 15"}),t.jsx("path",{d:"M21 13v2a4 4 0 0 1-4 4H3"})]}),reversible:t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[t.jsx("polyline",{points:"1 4 1 10 7 10"}),t.jsx("path",{d:"M3.51 15a9 9 0 1 0 2.13-9.36L1 10"})]}),irreversible:t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[t.jsx("path",{d:"M7.86 2h8.28L22 7.86v8.28L16.14 22H7.86L2 16.14V7.86L7.86 2z"}),t.jsx("line",{x1:"15",y1:"9",x2:"9",y2:"15"}),t.jsx("line",{x1:"9",y1:"9",x2:"15",y2:"15"})]}),after:t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[t.jsx("circle",{cx:"12",cy:"12",r:"10"}),t.jsx("polyline",{points:"12 6 12 12 16 14"})]})};function ls({profile:e}){if(e.irreversible)return t.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-md text-xs font-semibold border bg-danger-500/10 text-danger-700 border-danger-500/40",children:[t.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[t.jsx("path",{d:"M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"}),t.jsx("line",{x1:"12",y1:"9",x2:"12",y2:"13"}),t.jsx("line",{x1:"12",y1:"17",x2:"12.01",y2:"17"})]}),"Irreversible: review carefully"]});const s=e.verdict==="review";return t.jsxs("span",{className:`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-md text-xs font-semibold border ${s?"bg-warning-400/10 text-warning-700 border-warning-400/30":"bg-success-400/10 text-success-700 border-success-400/30"}`,children:[t.jsx("span",{"aria-hidden":!0,className:`h-1.5 w-1.5 rounded-full ${s?"bg-warning-500":"bg-success-500"}`}),s?"Review before applying":"Safe to apply"]})}const ge=24,bo=7,jo=Math.floor(bo/2)+1;function cs(e,s){const n=e*s;return`${String(Math.floor(n/60)).padStart(2,"0")}:${String(n%60).padStart(2,"0")}`}function vo(e,s){return Array.from({length:ge},(n,r)=>r>=e&&r<e+s)}function ds({label:e,tone:s,hours:n,aria:r,caption:a}){return t.jsxs(t.Fragment,{children:[t.jsx("span",{className:`text-xs font-medium uppercase tracking-wider ${s==="warning"?"text-warning-600":"text-success-600"}`,children:e}),t.jsx("div",{role:"img","aria-label":r,className:"flex h-3 w-full gap-px",children:n.map((i,o)=>t.jsx("div",{className:`min-w-0 flex-1 rounded-[1px] ${i?"bg-success-400":"bg-danger-200"}`},o))}),t.jsx("span",{className:"text-xs text-text-secondary whitespace-nowrap sm:text-right",children:a})]})}function No({schedule:e}){const{grid:s}=e,n=s[0]?.length??ge,r=1440/n,a=n/ge,i=Array.from({length:n},(N,k)=>{let j=0;for(let v=0;v<s.length;v++)s[v][k]&&j++;return j>=jo}),o=i.indexOf(!0),l=i.lastIndexOf(!0)+1,c=o!==-1&&i.slice(o,l).every(Boolean),d=s.every(N=>N.every((k,j)=>
3k===s[0][j])),u=s.reduce((N,k)=>N+k.filter(Boolean).length,0),m=u===0?0:Math.max(1,Math.round(u/s.length/a)),x=u===0,h=`${cs(o,r)} â ${cs(l,r)}`,p=c?i:vo(0,m),y=Array.from({length:p.length},()=>!0),b=c?d?`runs ${h}`:`runs ${h} most days`:x?"off all day":d?`runs â${m}h of 24 · every day`:`runs â${m}h of 24 · varies by day`,A=c?`After apply â runs ${h}${d?"":" most days"}`:x?"After apply â off all day":`After apply â runs about ${m} of ${ge} hours a day`;return t.jsxs("div",{className:"space-y-2.5",children:[t.jsxs("div",{className:"flex flex-col gap-1.5 sm:grid sm:grid-cols-[auto_1fr_auto] sm:items-center sm:gap-x-3 sm:gap-y-2.5",children:[t.jsx(ds,{label:"Today",tone:"warning",hours:y,aria:`Today â running ${ge} of ${ge} hours`,caption:"runs 24/7"}),t.jsx(ds,{label:"After apply",tone:"success",hours:p,aria:A,caption:b}),t.jsx("span",{"aria-hidden":"true",className:"hidden sm:block"}),t.jsx("span",{"aria-hidden":"true",className:"hidden sm:flex justify-between text-[10px] leading-none text-text-muted tabular-nums",children:(c?["00","06","12","18","24"]:["0h","12h","24h"]).map(N=>t.jsx("span",{children:N},N))}),t.jsx("span",{"aria-hidden":"true",className:"hidden sm:block"})]}),t.jsx("p",{className:R.caption,children:"Nothing is deleted, and nothing changes right away â the first stop happens at the next scheduled off-window. Detach the schedule anytime to return to 24/7."})]})}function wo(){return t.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[1fr_auto_1fr] items-stretch gap-3",children:[t.jsxs("div",{className:"rounded-lg border border-warning-400/30 bg-warning-400/5 px-3.5 py-3 space-y-1",children:[t.jsx("p",{className:"text-xs font-medium uppercase tracking-wider text-warning-600",children:"Today"}),t.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Runs 24 / 7"}),t.jsx("p",{className:R.bodyMuted,children:"Stays up through nights and weekends, paying for compute that serves no traffic."})]}),t.jsx("div",{className:"hidden lg:flex items-center text-text-muted","aria-hidden":"true",children:t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"}),t.jsx("polyline",{points:"12 5 19 12 12 19"})]})}),t.jsxs("div",{className:"rounded-lg border border-success-400/30 bg-success-400/5 px-3.5 py-3 space-y-1",children:[t.jsx("p",{className:"text-xs font-medium uppercase tracking-wider text-success-600",children:"After apply"}),t.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Off-hours schedule attached"}),t.jsx("p",{className:R.bodyMuted,children:"Stops when idle and starts before working hours. Nothing is deleted and the first stop happens at the next scheduled off-window â detach the schedule anytime to return to 24/7."})]})]})}function ko({rec:e,category:s}){const n=Nt(e,s),r=mo(n),a=fo[r.length]??"lg:grid-cols-3",{timezone:i}=f.useContext(Se);if(s==="schedule"){const o=Oe(e,i);return t.jsxs("div",{"data-testid":"rec-safety-impact",className:"border border-border-strong/60 rounded-lg px-4 py-3 space-y-3",children:[t.jsxs("div",{className:"flex items-center justify-between gap-3 flex-wrap",children:[t.jsx("span",{className:R.section,children:"Safety & Impact"}),t.jsx(ls,{profile:n})]}),o?.source==="proposed"?t.jsx(No,{schedule:o}):t.jsx(wo,{})]})}return t.jsxs("div",{"data-testid":"rec-safety-impact",className:"border border-border-strong/60 rounded-lg px-4 py-3 space-y-3",children:[t.jsxs("div",{className:"flex items-center justify-between gap-3 flex-wrap",children:[t.jsx("span",{className:R.section,children:"Safety & Impact"}),t.jsx(ls,{profile:n})]}),t.jsx("div",{className:`grid grid-cols-1 gap-y-4 ${a} lg:gap-x-6 lg:gap-y-6 lg:divide-x lg:divide-border-strong/40`,children:r.map((o,l)=>t.jsx("div",{className:`lg:px-4 ${l===0?"lg:pl-0":""}`,children:t.jsx(go,{icon:yo[o.iconKey],label:o.label,status:o.status,statusTone:o.statusTone,children:o.body})},o.key))})]})}const So=["instance_type","instance_class","machine_type","sku","tier"];function Co(e){return e.replace(/([a-z])([A-Z])/g,"$1 $2").toLowerCase()}function _o(e){const s=e?.specs??{};for(const r of So)if(s[r])return String(s[r]);const n=e?.resourceName||e?.resourceUid||"";return n?`${n} (current)`:"Current configuration"}function Ro(e){const s=Object.entries(e??{}).filter(([,n])=>n!=null&&n!=="");return s.length===0?"":s.length===1?String(s[0][1]):s.map(([n,r])=>`${Co(n)} ${r}`).join(" · ")}function Ao(e,s){return s>0?Math.min(100,Math.max(0,Math.round(e/s*100))):null}function Eo(e){return e?.irreversible?"Permanent":e?.verdict==="review"?"Review first":"Low"}function To(e,s){const n=Ro(e?.targetSpec),r=e?.currentCostUsd??0;if(!n||!(r>0))return[];const a=e?.savingsUsd??0,i=Nt(e,s);return[{id:"current",label:"Current",configuration:_o(e),costUsd:r,savingsUsd:0,savingsPct:null,risk:"None",baseline:!0,recommended:!1},{id:"recommended",label:"Option 1",configuration:n,costUsd:e?.optimizedCostUsd??null,savingsUsd:a,savingsPct:Ao(a,r),risk:Eo(i),baseline:!1,recommended:!0}]}function Io({storage:e}){const s=f.useId();if(!e)return null;const{pct:n,volume:r,total:a,countPhrase:i,lastPullLabel:o,dedup:l,summedVolume:c}=e,d=`${i?`${i} · `:""}${o?`last pulled ${o}`:"no pull recorded"}`,u=l?c?t.jsxs("p",{className:"text-xs text-text-muted",children:["ECR stores a shared layer once, so deleting these images frees less than the"," ",c," their sizes add up to â only blobs no other image still references are counted here."]}
3):null:t.jsx("p",{className:"text-xs text-text-muted",children:"Upper bound: ECR stores a shared layer once, so images that share layers free less than their sizes add up to."});return n===null?t.jsxs("div",{className:"space-y-1.5",children:[t.jsx("p",{className:"text-sm text-text-primary",children:l?i?`Deleting ${i} in this repository frees ${r}.`:`Deleting the unused images in this repository frees ${r}.`:i?`${r} across ${i} in this repository can be deleted.`:`${r} of unused images in this repository can be deleted.`}),u,t.jsx("p",{className:"text-xs text-text-muted",children:d})]}):t.jsxs("div",{className:"space-y-2",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[t.jsx("span",{className:"text-sm text-text-secondary min-w-0",id:s,children:l?"Repo storage freed by deleting stale images":"Repo storage held by stale images"}),t.jsxs("span",{className:"text-sm font-semibold tabular-nums text-text-primary shrink-0",children:[n,"%"]})]}),t.jsx("div",{className:"h-2 w-full rounded-full bg-surface-tertiary overflow-hidden",role:"progressbar","aria-labelledby":s,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n,"aria-valuetext":a?l?`${n}% â ${r} freed of ${a} stored`:`${n}% â ${r} stale of ${a}`:`${n}%`,children:t.jsx("div",{className:"h-full rounded-full bg-success-500",style:{width:`${n}%`}})}),t.jsxs("p",{className:"text-xs text-text-secondary",children:[r," ",l?`freed of ${a} stored`:`stale of ${a}`]}),u,t.jsx("p",{className:"text-xs text-text-muted",children:d})]})}const $o="ecr",Lo="ecr-image";function Mo(e){return e?.resourceType===$o&&!!e?.resourceUid}const De=[10,25,50],rn=De[0];De[De.length-1];const an=5,on=new Set(["name"]),Do="search";function Po(e){if(e&&typeof e=="object")return e;if(typeof e!="string"||e.trim()==="")return{};try{const s=JSON.parse(e);return s&&typeof s=="object"?s:{}}catch{return{}}}function Xe(e){const s=J(e);return s!==null&&s>0?s:null}const us=12;function ms(e){if(typeof e!="string"||e==="")return"";const s=e.indexOf(":"),n=s===-1?e:e.slice(s+1);return n.length>us?n.slice(0,us):n}function Bo(e,s){return s?e?`${e}@${s}`:s:""}function Oo(e){if(!e)return null;const s=Po(e.metadata),n=typeof s.image_digest=="string"?s.image_digest:"",r=e.uid??e.id??"";if(!n&&!r)return null;const a=Array.isArray(s.image_tags)?s.image_tags.filter(x=>typeof x=="string"&&x!==""):[],i=J(s.size_bytes),o=J(s.exclusive_bytes),l=J(s.manifest_children),c=typeof s.image_status=="string"?s.image_status.trim():"",d=c===""?null:c,u=Xe(s.last_archived_at),m=Xe(s.last_pull_time);return{uid:r,digest:n,shortDigest:ms(n),tags:a,tagCount:a.length,untagged:a.length===0,label:a[0]||ms(n)||e.name||"",sizeBytes:i,exclusiveBytes:o,manifestChildren:l,pushedAtSec:Xe(s.pushed_at),lastPullSec:m,neverPulled:m===null,imageStatus:d,archived:d!==null&&d.toUpperCase()==="ARCHIVED",lastArchivedAtSec:u}}function Fo({repoUid:e,page:s,pageSize:n,search:r,sortBy:a,sortOrder:i}){const o={view:"children",parent_uid:e,type:Lo,include:"metadata",page:s,limit:n},l=typeof r=="string"?r.trim():"";return l&&(o[Do]=l),on.has(a)&&(o.sort_by=a,o.sort_order=i==="desc"?"desc":"asc"),o}function ln({repoUid:e,page:s=1,pageSize:n=rn,search:r="",sortBy:a="",sortOrder:i="asc",enabled:o=!0}={}){const l=Fo({repoUid:e,page:s,pageSize:n,search:r,sortBy:a,sortOrder:i}),c=ce({queryKey:Q.resources.list(l),queryFn:()=>F.get("/resources",l),enabled:!!(o&&e),placeholderData:Os,staleTime:5*6e4}),d=f.useMemo(()=>(c.data?.items??[]).map(Oo).filter(Boolean),[c.data]),u=J(c.data?.total),m=u!==null&&u>0?u:null;return{rows:d,total:m,hasMore:!!c.data?.hasMore,isLoading:c.isLoading,isFetching:c.isFetching,isError:c.isError,error:c.error,refetch:c.refetch}}const xs=[{key:"label",label:"Image",kind:"image",sortKey:"name",sortScopeLabel:"primary tag or digest",w:300,sticky:!0,help:"The repository this image lives in, over the full `repository@digest` reference that deletes it â click the reference to copy it whole. Filter by an image tag using the box above."},{key:"sizeBytes",label:"Size",kind:"bytes",w:128,align:"right",help:"What the registry reports for this image, including any layers it shares with other images. ECR stores a shared layer once, so deleting the image does NOT necessarily free this much â the âfreesâ figure beneath a
3size is what deleting that image on its own would reclaim. Rows with no âfreesâ figure predate the measurement; their reclaim is unknown, not equal to their size."},{key:"lastPullSec",label:"Last pull",kind:"elapsed",w:122,help:"How long since anyone pulled this image â the staleness signal this table exists to rank. Hover a value for the exact date. âNeverâ means the registry has no pull recorded for the image at all, the strongest safe-to-delete signal there is: an absent value, not a zero."},{key:"pushedAtSec",label:"Pushed",kind:"elapsed",w:122,help:"How long since this image was pushed to the repository. Hover a value for the exact date."},{key:"manifestChildren",label:"Type",kind:"type",w:110,help:"An âImage indexâ is a multi-architecture manifest list: it stores only the document naming the per-architecture images beneath it, so it holds no image data of its own and its Size is blank rather than zero. Deleting it is still required â the tag points at the index."},{key:"tags",label:"Image tags",kind:"tags",w:170,help:"The OCI tags pointing at this image â the imageâs NAME, what `docker pull` resolves. These are NOT the repositoryâs AWS resource tags: ECR attaches those to the repository only, never to an image. An image with none is untagged, the ordinary state for a prunable image since moving a tag leaves the old digest behind."}],Uo=new Set(["sizeBytes","lastPullSec","pushedAtSec"]);function cn(e){return Number.isFinite(e?.manifestChildren)&&e.manifestChildren>0}function zo({row:e}){return cn(e)?t.jsx(O,{content:un,placement:"top",children:t.jsxs("span",{className:"text-text-secondary",children:["Image index"," ",t.jsxs("span",{className:`${R.caption} text-text-muted normal-case`,children:["(",e.manifestChildren,")"]}),t.jsxs("span",{className:"sr-only",children:[" ","referencing ",e.manifestChildren," image manifests, listed separately in this table"]})]})}):t.jsx("span",{className:"text-text-secondary",children:"Image"})}function Wo({row:e}){const s=Array.isArray(e.tags)?e.tags.filter(i=>typeof i=="string"&&i):[];if(s.length===0)return t.jsx(O,{content:"No OCI tag points at this image.",placement:"top",children:t.jsx("span",{className:"italic text-text-muted",children:"untagged"})});const[n,r,...a]=s;return t.jsxs("span",{className:"inline-flex min-w-0 flex-wrap items-center gap-1",children:[t.jsx(ps,{value:n}),r?t.jsx(ps,{value:r}):null,a.length>0?t.jsx(O,{content:a.join(", "),placement:"top",children:t.jsxs("span",{className:`${R.caption} shrink-0 text-text-muted`,children:[t.jsxs("span",{children:["+",a.length]}),t.jsxs("span",{className:"sr-only",children:[" more tags: ",a.join(", ")]})]})}):null]})}function ps({value:e}){return t.jsx(O,{content:e,placement:"top",onlyOnOverflow:!0,children:t.jsx("span",{className:"max-w-[9rem] truncate rounded bg-surface-tertiary/60 px-1.5 py-0.5 font-mono text-[11px] text-text-secondary",children:e})})}function dn({row:e}){const{sizeBytes:s,exclusiveBytes:n}=e;return cn(e)?t.jsx(O,{content:un,placement:"top",children:t.jsxs("span",{className:"text-text-muted",children:["â",t.jsx("span",{className:"sr-only",children:"not applicable: an image index stores no image data"})]})}):Number.isFinite(n)&&Number.isFinite(s)&&n<s?t.jsxs("span",{className:"flex flex-col items-end leading-tight",children:[t.jsx("span",{children:re(s)}),t.jsx(O,{content:Ko,placement:"top",children:t.jsxs("span",{className:`mt-0.5 ${R.caption} font-medium normal-case`,children:[t.jsxs("span",{children:["frees ",re(n)]}),t.jsx("span",{className:"sr-only",children:" if this image alone is deleted"})]})})]}):t.jsx("span",{children:re(s)})}const Ko="What deleting THIS image on its own would free. The rest of its size is layer blobs other images still reference, and ECR stores a shared layer once.",un="A multi-architecture index. It stores only the manifest document listing the images below it, so it holds no image data of its own â the size AWS reports for an index just restates its largest image, which is already counted on its own row. Deleting it is still required: the tag points here.";function Ho({status:e,archived:s,archivedAtSec:n}
3){const r=Number.isFinite(n)?le(n*1e3):null,a=s?"Archived":e,i=s?`${qo}${r?` Archived ${r}.`:""}`:`The registry reports this image as ${e}.`;return t.jsx(O,{content:i,placement:"top",children:t.jsxs("span",{className:"shrink-0 rounded bg-warning-400/15 px-1.5 py-0.5 text-[11px] font-medium text-warning-600",children:[a,r?t.jsxs("span",{className:"sr-only",children:[", archived ",r]}):null]})})}const qo="This image is in the archive tier â it cannot be pulled until it is restored, so nothing is currently depending on it.",hs=34,fs=6;function Vo(e){if(typeof e!="string"||e.length<=hs)return e;const s=hs-fs-1;return`${e.slice(0,s)}â¦${e.slice(-fs)}`}function mn({row:e,repoName:s}){const n=Bo(s,e.digest),r=s||e.shortDigest||"â";return t.jsxs("span",{className:"flex min-w-0 flex-col leading-tight",children:[t.jsxs("span",{className:"flex min-w-0 items-baseline gap-1.5",children:[t.jsx("span",{className:"truncate text-text-primary",title:r,children:r}),e.imageStatus?t.jsx(Ho,{status:e.imageStatus,archived:e.archived,archivedAtSec:e.lastArchivedAtSec}):null]}),n?t.jsx(nt,{uid:n,label:Vo(n),ariaLabel:`Copy full image reference ${n}`,className:"mt-0.5"}):t.jsx("span",{className:`mt-0.5 ${R.caption}`,children:"â"})]})}function it({seconds:e,neverLabel:s,neverHint:n}){const r=Number.isFinite(e)?e*1e3:null,a=r===null?null:$r(r);if(!a)return n?t.jsx(O,{content:n,placement:"top",children:t.jsx("span",{children:s})}):t.jsx("span",{children:s});const i=le(r);return i?t.jsx(O,{content:i,placement:"top",children:t.jsxs("span",{children:[t.jsx("span",{children:a}),t.jsxs("span",{className:"sr-only",children:[", ",i]})]})}):t.jsx("span",{children:a})}const xn="The registry has no pull recorded for this image.";function Go(e,s){const n=s[e.key];return e.kind==="bytes"?t.jsx(dn,{row:s}):e.kind==="elapsed"?e.key==="lastPullSec"?t.jsx(it,{seconds:s.neverPulled?null:n,neverLabel:"Never",neverHint:xn}):t.jsx(it,{seconds:n,neverLabel:"â"}):n==null||n===""?"â":String(n)}function Zo(e,s,n,r){let a=e[n],i=s[n];return Uo.has(n)?(a=Number.isFinite(a)?a:-1/0,i=Number.isFinite(i)?i:-1/0):(a=a==null?"":String(a),i=i==null?"":String(i)),a<i?r==="asc"?-1:1:a>i?r==="asc"?1:-1:0}function Yo({colCount:e,rowCount:s}){return t.jsx(t.Fragment,{children:Array.from({length:s},(n,r)=>t.jsx("tr",{"aria-hidden":"true",children:t.jsx("td",{colSpan:e,className:"border-b border-border-strong/25 px-3 py-2",children:t.jsx("div",{className:"h-5 animate-pulse rounded bg-surface-tertiary/70"})})},r))})}function pn({error:e,onRetry:s}){return t.jsxs("div",{className:"rounded-lg border border-border-strong/40 px-4 py-6 text-center",children:[t.jsx("p",{className:"text-sm text-text-primary",children:"Could not load this repositoryâs images."}),e?.message&&t.jsx("p",{className:`mt-1 ${R.caption}`,children:e.message}),t.jsx("button",{type:"button",onClick:s,className:"mt-3 rounded-md border border-border-strong/60 px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-surface-tertiary",children:"Retry"})]})}const Qo=300;function Jo({repoUid:e,repoName:s}){const[n,r]=f.useState(""),[a,i]=f.useState({key:"name",dir:"asc"}),[o,l]=f.useState(1),[c,d]=f.useState(rn),u=Vr(n,Qo),m=on.has(a.key),{rows:x,total:h,hasMore:p,isLoading:y,isFetching:b,isError:A,error:N,refetch:k}=ln({repoUid:e,page:o,pageSize:c,search:u,sortBy:m?a.key:"",sortOrder:a.dir}),j=xs,v=f.useMemo(()=>{if(m)return x;const g=x.slice();return g.sort((E,_)=>Zo(E,_,a.key,a.dir)),g},[x,m,a]),L=f.useMemo(()=>x.reduce((g,E)=>g+(Number.isFinite(E.sizeBytes)?E.sizeBytes:0),0),[x]),U=g=>{l(1),i(E=>E.key===g?{key:g,dir:E.dir==="asc"?"desc":"asc"}:{key:g,dir:g==="name"?"asc":"desc"})},Z=g=>{l(1),r(g)},w=u.trim().length>0,M=xs.find(g=>(g.sortKey||g.key)===a.key),$=M?.sortScopeLabel??M?.label??a.key;return t.jsxs("div",{children:[t.jsxs("div",{className:"mb-1 flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1",children:[t.jsx("p",{className:R.section,children:"Stale images in this repository"}),t.jsxs("span",{className:R.numericMuted,children:[h===null?`${x.length.toLocaleString()}
3+`:h.toLocaleString()," ",w?"matching":"stale"," image",h===1?"":"s",L>0?` · ${re(L)} of image size on this page`:""]})]}),t.jsx("p",{className:R.caption,children:"Images RC-022 would delete, as last discovered. Each row is one image in this repository."}),t.jsxs("div",{className:"mb-2.5 mt-3 flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("div",{className:"relative",children:[t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"absolute left-2.5 top-1/2 -translate-y-1/2 text-text-muted","aria-hidden":"true",children:[t.jsx("circle",{cx:"11",cy:"11",r:"8"}),t.jsx("path",{d:"m21 21-4.3-4.3"})]}),t.jsx("input",{type:"text",value:n,onChange:g=>Z(g.target.value),placeholder:"Filter by tag or digest","aria-label":"Filter images by primary tag or digest",className:"w-56 max-w-full rounded-md border border-border-strong/50 bg-surface-tertiary/40 py-1.5 pl-8 pr-3 text-xs text-text-primary placeholder:text-text-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40"})]}),t.jsx("div",{className:"flex items-center gap-3",children:b&&!y&&t.jsx("span",{className:R.caption,role:"status",children:"Loadingâ¦"})})]}),t.jsxs("p",{className:`mb-2.5 ${R.caption}`,children:[m?`Sorted by ${$} across every image in this repository.`:`Sorted by ${$} within this page only â other pages are not reordered.`,w?" Filter matches the primary tag or the digest, across the whole repository.":""]}),A?t.jsx(pn,{error:N,onRetry:k}):t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"max-h-[calc(100vh-22rem)] overflow-auto overscroll-contain rounded-lg border border-border-strong/40",children:t.jsxs("table",{className:"w-full table-auto border-collapse text-xs",children:[t.jsx("caption",{className:"sr-only",children:"Stale images in this ECR repository: repository and copyable reference, size and â where it was measured â the storage deleting that image alone would free, time since the last pull, and time since the push."}),t.jsx("thead",{children:t.jsx("tr",{children:j.map(g=>{const E=g.sortKey||g.key,_=g.kind!=="tags"&&g.kind!=="type",T=_&&a.key===E;return t.jsx("th",{scope:"col",style:{minWidth:g.w},"aria-sort":_?T?a.dir==="asc"?"ascending":"descending":"none":void 0,className:`sticky top-0 z-20 whitespace-nowrap border-b border-border-strong/60 bg-surface-tertiary px-3 py-2 font-semibold text-text-muted shadow-[0_2px_5px_-3px_rgba(0,0,0,0.5)] ${g.align==="right"?"text-right":"text-left"} ${g.sticky?"left-0 z-30 border-r border-border-strong/40":""}`,children:_?t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsxs("button",{type:"button",onClick:()=>U(E),className:`inline-flex items-center gap-1 transition-colors hover:text-text-secondary ${T?"text-text-primary":""}`,children:[g.label,t.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",className:`transition-opacity ${T?"opacity-100":"opacity-0"}`,"aria-hidden":"true",children:a.dir==="asc"?t.jsx("path",{d:"m18 15-6-6-6 6"}):t.jsx("path",{d:"m6 9 6 6 6-6"})})]}),g.help&&t.jsx(Bt,{text:g.help,placement:"top"})]}):t.jsxs("span",{className:"inline-flex items-center gap-1",children:[g.label,g.help&&t.jsx(Bt,{text:g.help,placement:"top"})]})},g.key)})})}),t.jsxs("tbody",{children:[y&&t.jsx(Yo,{colCount:j.length,rowCount:c>10?10:c}),!y&&v.map(g=>t.jsx("tr",{className:"odd:bg-surface-secondary/20 hover:bg-primary-600/5",children:j.map(E=>t.jsx("td",{style:{minWidth:E.w},className:`whitespace-nowrap border-b border-border-strong/25 px-3 py-2 align-middle ${E.align==="right"?"text-right tabular-nums":"text-left"} ${E.sticky?"sticky left-0 z-10 border-r border-border-strong/40 bg-surface-secondary font-medium text-text-primary":"text-text-secondary"}`,children:E.kind==="image"?t.jsx(mn,{row:g,repoName:s}):E.kind==="tags"?t.jsx(Wo,{row:g}):E.kind==="type"?t.jsx(zo,{row:g}):Go(E,g)},E.key))},g.uid)),!y&&v.length===0&&t.jsx("tr",{children:t.jsx("td",{colSpan:j.length,className:"px-3 py-6",children:t.jsx(rr,{message:w?`No image in this repository matches â${u.trim()}â.`:o>1?"This page is empty â the list is shorter than it was.":"No stale images are recorded for this repository."})})})]})]})}),(h!==null||p||o>1)&&t.jsx("div",{className:"mt-2",children:t.jsx(qr,{page:o,total:h??void 0,count:x.length,hasMore:p,pageSize:c,label:"images",onPageChange:l,onPageSizeChange:g=>{d(g),l(1)},pageSizeOptions:De})})]})]})}function Xo({rows:e,total:s,repoName:n,onViewAll:r}){return e.length?t.jsxs("div",{className:"mt-3 border-t border-border-strong/40 pt-3",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-2",children:[t.jsx("p",{className:R.section,children:"Stale images"}),t.jsxs("button",{type:"button",onClick:r,className:"text-[0.6875rem] font-medium text-primary-600 transition-colors hover:text-primary-500",children:[s===null?"See all":`All ${s.toLocaleStr
3ing()}`," âº"]})]}),t.jsxs("p",{className:R.caption,children:[s===null?`First ${e.length} in name order`:`First ${e.length} of ${s.toLocaleString()} in name order`," â not the largest or the stalest."]}),t.jsxs("table",{className:"mt-1.5 w-full border-collapse text-xs",children:[t.jsx("caption",{className:"sr-only",children:"The first images RC-022 would delete from this repository, in name order"}),t.jsx("thead",{children:t.jsxs("tr",{className:"text-text-muted",children:[t.jsx("th",{scope:"col",className:"w-full py-1 pr-2 text-left font-medium",children:"Image"}),t.jsx("th",{scope:"col",className:"w-px px-1 py-1 text-right font-medium whitespace-nowrap",children:"Size"}),t.jsx("th",{scope:"col",className:"w-px px-1 py-1 text-left font-medium whitespace-nowrap",children:"Last pull"})]})}),t.jsx("tbody",{children:e.map(a=>t.jsxs("tr",{className:"border-t border-border-strong/20",children:[t.jsx("td",{className:"w-full max-w-0 py-1 pr-2 align-top text-text-secondary",children:t.jsx(mn,{row:a,repoName:n})}),t.jsx("td",{className:"w-px whitespace-nowrap px-1 py-1 text-right font-medium tabular-nums text-text-primary",children:t.jsx(dn,{row:a})}),t.jsx("td",{className:"w-px whitespace-nowrap px-1 py-1 tabular-nums text-text-muted",children:t.jsx(it,{seconds:a.neverPulled?null:a.lastPullSec,neverLabel:"Never",neverHint:xn})})]},a.uid))})]})]}):null}function el(){return t.jsxs("div",{className:"mt-3 border-t border-border-strong/40 pt-3","aria-hidden":"true",children:[t.jsx("div",{className:"mb-2 h-3 w-28 animate-pulse rounded bg-surface-tertiary"}),t.jsx("div",{className:"space-y-1.5",children:Array.from({length:an},(e,s)=>t.jsx("div",{className:"h-4 animate-pulse rounded bg-surface-tertiary/70"},s))})]})}function tl({rec:e}){const[s,n]=f.useState(!1),r=e?.resourceUid??"",a=e?.resourceName??"",{rows:i,total:o,isLoading:l,isError:c,error:d,refetch:u}=ln({repoUid:r,page:1,pageSize:an,sortBy:"name",sortOrder:"asc",enabled:!!r});return r?l?t.jsx(el,{}):c?t.jsx("div",{className:"mt-3 border-t border-border-strong/40 pt-3",children:t.jsx(pn,{error:d,onRetry:u})}):i.length?t.jsxs(t.Fragment,{children:[t.jsx(Xo,{rows:i,total:o,repoName:a,onViewAll:()=>n(!0)}),t.jsx(be,{open:s,onClose:()=>n(!1),wide:!0,title:a?`Stale images · ${a}`:"Stale images",children:t.jsx(Jo,{repoUid:r,repoName:a},r)})]}):t.jsx("p",{className:`mt-3 border-t border-border-strong/40 pt-3 ${R.caption}`,children:"Per-image detail has not been discovered for this repository yet."}):null}const sl=()=>{};function gs({schedule:e}){if(!e)return null;const{grid:s,source:n,timezone:r,idlePct:a,slotMinutes:i=60}=e,o=n==="proposed"?"Weekly schedule":"Weekly utilization";return t.jsxs("section",{"aria-label":o,className:"space-y-2",children:[t.jsxs("div",{className:"flex items-baseline justify-between gap-3 flex-wrap",children:[t.jsx("span",{className:"text-sm font-medium text-text-primary min-w-0",children:o}),a!==null&&t.jsxs("span",{className:"shrink-0 text-right",children:[t.jsxs("span",{className:"text-sm font-semibold tabular-nums text-warning-600",children:[a,"% idle"]}),t.jsx("span",{className:"text-xs text-text-muted",children:" · repeating pattern"})]})]}),t.jsx(Ar,{grid:s,onChange:sl,slotMinutes:i,readOnly:!0}),t.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1",children:[t.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs text-text-muted",children:[t.jsx("span",{className:"w-2.5 h-2.5 rounded-sm bg-success-400 shrink-0"}),n==="proposed"?"running":"active"]}),t.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs text-text-muted",children:[t.jsx("span",{className:"w-2.5 h-2.5 rounded-sm bg-danger-200 shrink-0"}),n==="proposed"?"stopped â schedule stops it here":"idle"]})]}),r&&t.jsx("p",{className:"text-xs leading-relaxed",children:t.jsxs("span",{className:"text-text-muted whitespace-nowrap",children:["Times shown in ",r]})})]})}function nl(e){return e?.observation&&e?.recommendation?{observation:e.observation,recommendation:e.recommendation}:null}const rl=new Set(["critical","high","medium","low","info"]),al={critical:"the saving here is very large next to what this organisation spends in a typical day, at the time it was rated",high:"the saving here is large next to what this organisation spends in a typical day, at the time it was rated",medium:"the saving here is moderate next to what this organisation spends in a typical day, at the time it was rated",low:"the saving here is small next to what this organisation spends in a typical day, at the time it was rated",info:"the saving here is small next to what this organisation spends in a typical day, at the time it was rated"};
3function il(e){const s=typeof e?.severityReason=="string"?e.severityReason.trim():"";if(!s)return"";const n=s.replace(/\.$/,"");return/^[A-Z][A-Z0-9]/.test(n)?n:n.charAt(0).toLowerCase()+n.slice(1)}const ol={auto:"ZopNight can apply this for you",guided:"ZopNight can apply this for you, behind a confirmation step"};function ll(e){return e&&e.charAt(0).toUpperCase()+e.slice(1)}function cl(e){return e.charAt(0).toUpperCase()+e.slice(1)}function dl(e){const s=e?.evidence,n=Number(s?.periodDays),r=typeof s?.metricName=="string"?s.metricName.trim():"";return!Number.isFinite(n)||n<=0?"":r?`measured from ${r} over ${n} ${n===1?"day":"days"}`:`measured over ${n} ${n===1?"day":"days"}`}function ul(e){return ol[e?.remediationKind]||""}function ml(e){const s=typeof e?.severity=="string"?e.severity.toLowerCase().trim():"";if(!rl.has(s))return null;const n=!!e?.severityDetail,r=il(e),a=r!=="";let i="";n?i=al[s]:a&&(i=r);const o=[n&&a?r:"",n?dl(e):"",ul(e)].filter(Boolean),l=[i,...o.map(ll)].filter(Boolean);return{level:s,scored:n,explained:a,sentence:l.length?`${l.join(". ")}.`:""}}function xl(e){if(!e)return{kind:"empty",items:[]};const s=e.trim(),n=s.split(` 4`);if(n.some(a=>a.trim().startsWith("â¢")))return{kind:"bullets",items:n.map(i=>i.trim()).filter(Boolean).map(i=>i.replace(/^â¢\s*/,""))};if(n.length>1){const a=n.filter(i=>i.trim()).map(i=>({text:i.trim(),indented:/^\s+\S/.test(i)}));if(a.length>1)return{kind:"lines",items:a}}const r=pl(s);return r.length>1?{kind:"sentences",items:r}:{kind:"single",items:[s]}}function pl(e){const s=[];let n=0;for(let a=0;a<e.length-1;a++){const i=e[a];if(i!=="."&&i!=="!"&&i!=="?")continue;const o=e[a-1]??"";if(!/[a-z0-9)\]]/.test(o))continue;const l=/\S*$/.exec(e.slice(0,a))[0];if(/^[A-Za-z](\.[A-Za-z])+$/.test(l))continue;const c=e.slice(a+1),d=/^(\s+)([A-Z])/.exec(c);d&&(s.push(e.slice(n,a+1).trim()),n=a+1+d[1].length)}const r=e.slice(n).trim();return r&&s.push(r),s}function hl({text:e}){const{kind:s,items:n}=xl(e);if(s==="empty")return t.jsx("p",{className:"text-sm text-text-muted italic",children:"No description provided."});if(s==="bullets")return t.jsx("ul",{className:"space-y-2",children:n.map((r,a)=>t.jsxs("li",{className:"flex gap-2 text-sm text-text-primary leading-relaxed",children:[t.jsx("span",{className:"text-primary-500 mt-0.5 shrink-0",children:"â¢"}),t.jsx("span",{children:r})]},a))});if(s==="lines"||s==="sentences"){const r=s==="lines"?n:n.map(a=>({text:a,indented:!1}));return t.jsx("div",{className:"space-y-2",children:r.map(({text:a,indented:i},o)=>t.jsx("p",{className:i?"text-sm text-text-secondary leading-relaxed pl-3 border-l-2 border-border-strong/40":"text-sm text-text-primary leading-relaxed",children:a},o))})}return t.jsx("p",{className:"text-sm text-text-primary leading-relaxed",children:n[0]})}function ys({items:e}){return e?.length?t.jsxs("section",{"aria-label":"Why this fired",className:"pt-3 border-t border-border-strong/40",children:[t.jsx("h4",{className:"text-[11px] font-semibold uppercase tracking-wider text-text-muted mb-2",children:"Why this fired"}),t.jsx("dl",{className:"space-y-1.5",children:e.map((s,n)=>t.jsxs("div",{className:"flex items-start justify-between gap-3 text-sm",children:[t.jsx("dt",{className:"text-text-muted min-w-0",children:s.label}),t.jsx("dd",{className:"text-text-primary font-medium text-right min-w-0 break-words",children:s.value})]},`${s.label}-${n}`))})]}):null}function bs({children:e,action:s}){return t.jsxs("div",{className:"flex items-center justify-between gap-3 px-4 py-2.5 bg-surface-tertiary/50 border-b border-border-strong/40",children:[t.jsx("span",{className:"text-xs font-medium text-text-muted uppercase tracking-wider",children:e}),s]})}function fl({rec:e}){const s=nl(e),n=yl(e),r=e?.nonMetricEvidence??[],a=!!s;return t.jsxs(t.Fragment,{children:[a&&t.jsx(V,{title:"Observation",meta:n??void 0,testId:"finding-observation",children:t.jsxs("div",{className:"space-y-3",children:[t.jsx("p",{className:"text-sm text-text-secondary leading-relaxed",children:s.observation}),t.jsx(ys,{items:r})]})}),t.jsx(V,{title:a?"Recommendation":"Finding",meta:a?void 0:n??void 0,testId:"finding-recommendation",children:t.jsxs("div",{className:"space-y-3",children:[a?t.jsx("p",{className:"text-sm text-text-secondary leading-relaxed",children:s.recommendation}):t.jsx(hl,{text:e.description||e.title}),!a&&t.jsx(ys,{items:r})]})})]})}function gl({rec:e}){const s=ml(e),n=Dr[s?.level];return s?t.jsx("div",{"data-testid":"why-this-level",className:`border-l-2 ${n?.border??"border-border-strong"} pl-3 py-0.5`,children:t.jsxs("p",{className:"text-sm text-text-secondary leading-relaxed",children:[t.jsxs("span",{className:"font-semibold text-text-primary",children:[cl(s.level)," severity"]}),s.sentence?t.jsxs(t.Fragment,{children:[" â ",s.sentence]}):null]})}):null}function yl(e){const n=je(e?.evidenceMetrics,e?.evidence).find(r=>r?.periodDays>0);return n?`Based on the last ${n.periodDays} days of metrics`:null}function bl({rec:e,nowSec:s}){const n=vt(e,s),r=nn(e),{timezone:a}=f.useContext(Se),i=Oe(e,a),o=n||r!==null||i!==null;return i!==null&&r===null?t.jsxs("div",{className:"border border-border-strong/60 rounded-lg overflow-hidden",children:[t.jsx(bs,{children:"Evidence"}),t.jsx("section",{"aria-label":"Evidence",className:"px-4 py-3",children:t.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-x-6 gap-y-4 items-start min-w-0",children:[t.jsx("div",{className:"min-w-0",children:t.jsx(gs,{schedule:i})}),t.jsx("div",{className:"min-w-0",children:t.jsx(en,{rec:e,embedded:!0},`live-metrics-${e.id}`)})]})})]}):o?t.jsx("div",{className:"border border-border-strong/60 rounded-lg overflow-hidden",children:t.jsx("div",{className:"grid grid-cols-1",children:o&&t.jsxs("section",{className:"flex flex-col min-w-0","aria-label":"Evidence",children:[t.jsx(bs,{children:"Evidence"}),t.jsxs("div",{className:"px-4 py-3 space-y-3",children:[t.jsx(Io,{storage:r}),r!==null&&Mo(e)&&t.jsx(tl,{rec:e},`ecr-images-${e.id}`),i&&t.jsx(gs,{schedule:i}),n&&t.jsx(tn,{evidenceMetrics:e.evidenceMetrics,evidence:e.evidence,activitySeries:e.activitySeries,resourceUid:e.resourceUid,resourceName:e.resourceName||e.resourceUid},e.id)]})]})})}):null}const jl={cpu:"CPU",memory:"Memory",network_in:"Network In",network_out:"Network Out",disk_read_ops:"Disk Reads",disk_write_ops:"Disk Writes",iops_util:"IOPS
4Usage",queue_depth:"Queue Depth",db_connections:"DB Connections",db_qps:"DB Queries/sec",invocations:"Invocations",duration:"Duration",error_rate:"Error Rate",cache_hit:"Cache Hit Rate",uptime:"Uptime",gpu:"GPU",gpu_memory:"GPU Memory",request_units:"Request Units",throttled_ops:"Throttled Ops"},vl={avg:"average",max:"peak",min:"lowest",p95:"95th-percentile",p99:"99th-percentile",sum:"total"},Nl={lt:"below",lte:"at or below",gt:"above",gte:"at or above",eq:"at"};function wl(e){return jl[e]??e}function ue(e){return String(Number(e.toFixed(2)))}function js(e){const s=Math.abs(e);return s>=1e9?`${ue(e/1e9)} GB`:s>=1e6?`${ue(e/1e6)} MB`:s>=1e3?`${ue(e/1e3)} KB`:`${ue(e)} B`}function vs(e,s){return typeof e!="number"||!isFinite(e)?null:s==="%"?`${ue(e)}%`:s==="B/s"?`${js(e)}/s`:s==="B"||s==="bytes"?js(e):s?`${ue(e)} ${s}`:ue(e)}function Ae({label:e,children:s}){return t.jsxs("div",{className:"flex gap-3 text-sm",children:[t.jsx("span",{className:"w-24 shrink-0 text-text-muted",children:e}),t.jsx("span",{className:"min-w-0 text-text-primary",children:s})]})}function kl({rec:e}){const{data:s}=Gr(e?.policyId),n=s?.name,r=yt(e);if(!r)return null;const a=Array.isArray(r.signals)?r.signals:[],i=je(e?.evidenceMetrics,e?.evidence),o=qa(e),l=a.length>1,c=r.decision?.mode==="any"?"any condition is true":"all conditions are true";return t.jsxs("div",{className:"space-y-2",children:[n&&t.jsx(Ae,{label:"Policy",children:n}),o&&t.jsx(Ae,{label:"Applies to",children:o}),a.map((d,u)=>{const m=wl(d.concept),x=vl[d.agg]??d.agg,h=Nl[d.op]??d.op,p=vs(d.threshold,d.unit),y=d.windowDays?`${d.windowDays}-day `:"",b=vs(i[u]?.observed,d.unit);return t.jsxs(Ae,{label:m,children:[y,x," ",h," ",t.jsx("span",{className:"font-medium",children:p}),b&&t.jsxs(t.Fragment,{children:[" ","â measured ",t.jsx("span",{className:"font-semibold",children:b})]})]},d.letter||u)}),l&&t.jsx(Ae,{label:"Match",children:c})]})}const Sl={already_scheduled:"Already scheduled",stale_metrics:"Metrics may be stale",insufficient_coverage:"Not enough data yet",insufficient_peak_coverage:"Not enough peak/trough data yet",peak_exceeds_ceiling:"Low average, high peaks",memory_resident:"Memory-bound",stateful_resource:"Stateful data service",no_measured_saving:"No saving to show yet"};function ot(e){return Sl[e]??"May not be worth acting on"}function Cl(e){return!Array.isArray(e)||e.length===0?null:e.find(s=>s?.severity==="block")??e[0]}const _l=t.jsxs("svg",{width:"13",height:"13",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[t.jsx("path",{d:"M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"}),t.jsx("line",{x1:"12",y1:"9",x2:"12",y2:"13"}),t.jsx("line",{x1:"12",y1:"17",x2:"12.01",y2:"17"})]});function Rl({gates:e}){const s=Cl(e);if(!s)return null;const n=e.length>1?` +${e.length-1}`:"",r=e.map(a=>a?.detail).filter(Boolean).join(` 5`)||ot(s.reason);return t.jsx(O,{content:r,children:t.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md border border-warning-400/40 bg-warning-400/5 text-xs text-text-secondary cursor-default",children:[t.jsx("span",{"aria-hidden":!0,className:"text-warning-600",children:_l}),ot(s.reason),n]})})}function Al({gates:e}){return!Array.isArray(e)||e.length===0?null:t.jsxs("div",{className:"rounded-lg border border-warning-400/30 bg-warning-400/10 p-3 text-sm text-text-secondary",role:"note",children:[t.jsx("p",{className:"font-medium text-text-primary",children:"This matched your policy â but may not be worth acting on"}),t.jsx("ul",{className:"mt-1 list-disc pl-4 space-y-0.5",children:e.map((s,n)=>t.jsx("li",{children:s?.detail||ot(s?.reason)},s?.reason??n))})]})}const El=new Set(["delete","stop","resize"]),Tl=new Set(["pause","schedule","configure"]),Il=new Set(["spot","migration","arch-migration"]),$l=new Set(["commitment","hybrid"]);function hn(e,s,n){const r=typeof n=="string"?n.trim():"";return r===""?!1:e.has(r)?!0:!s.has(r)}function Ll(e){return hn(El,Tl,e)}function Ml(e){return hn(Il,$l,e)}function Dl(e){return Ll(e?.lever)||Ml(e?.mechanism)}const Pl=t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",className:"mt-0.5 shrink-0",children:[t.jsx("path",{d:"M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"}),t.jsx("line",{x1:"12",y1:"9",x2:"12",y2:"13"}),t.jsx("line",{x1:"12",y1:"17",x2:"12.01",y2:"17"})]}),Bl=t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",className:"mt-0.5 shrink-0",children:[t.jsx("circle",{cx:"12",cy:"12",r:"10"}),t.jsx("line",{x1:"12",y1:"16",x2:"12",y2:"12"}),t.jsx("line",{x1:"12",y1:"8",x2:"12.01",y2:"8"})]});function Ol({rec:e,category:s,onBlastRadius:n}){const r=Nt(e,s),a=e?.implementationTags??[],i=r.verdict==="review"||Dl(e),o=r.verdict==="review"&&!r.unclassified?r.reversible:"";if(!o&&a.length===0&&!i)return null;const l=i?"font-semibold text-warning-700":"font-medium text-text-primary";return t.jsxs("div",{role:"note","data-testid":"implementation-notes","data-severity":i?"disruptive":"descriptive",className:`flex items-start gap-2 w-full rounded-lg border px-3 py-2 text-xs leading-relaxed ${i?"border-warning-400/40 bg-warning-400/10 text-text-secondary":"border-border-strong/60 bg-surface-tertiary/30 text-text-secondary"}`,children:[t.jsx("span",{className:i?"text-warning-600":"text-text-muted",children:i?Pl:Bl}),t.jsxs("div",{className:"min-w-0 flex flex-col gap-0.5",children:[a.length>0&&t.jsx("p",{className:l,children:a.map((c,d)=>t.jsxs("span",{children:[d>
50&&t.jsx("span",{"aria-hidden":!0,className:"font-normal text-text-muted",children:" · "}),t.jsx("span",{children:c})]},c))}),o&&t.jsx("p",{className:a.length>0?"":l,children:o}),(o||i)&&t.jsxs("p",{children:["Review the"," ",n&&e?.resourceUid?t.jsx("button",{type:"button",onClick:n,className:"font-medium text-text-primary underline underline-offset-2 hover:text-primary-600 transition-colors",children:"blast radius"}):t.jsx("span",{className:"font-medium text-text-primary",children:"blast radius"})," ","before you remediate."]})]})]})}const Fl=["instance_type","instance_class","machine_type"];function fn(e){return e?Fl.find(s=>e[s])??"":""}function Ul(e){const s=fn(e);return s?e[s]:""}const Ns={engine:"Engine",engine_version:"Version",multi_az:"Multi-AZ",storage_gb:"Storage",allocated_storage_gb:"Storage",instance_class:"Instance Type",instance_type:"Instance Type",storage_type:"Storage type",region:"Region",platform:"Platform",architecture:"Architecture",root_device_type:"Root Device",tenancy:"Tenancy",os_type:"OS",osType:"OS",resource_group:"Resource Group",resourceGroup:"Resource Group",resource_uid:"Resource ID",purchase_type:"Purchase type",machine_type:"Machine Type",machineType:"Machine Type",lifecycle_policy_present:"Lifecycle policy",image_scanning_enabled:"Scan on push",immutable_tags:"Immutable tags",repository_policy_present:"Repository policy"};function zl(e,s){return e==="storage_gb"||e==="allocated_storage_gb"?`${s} GB`:s}function Wl({targetSpec:e}){const s=Object.entries(e||{}).filter(([,n])=>n!=null&&n!=="");return s.length===0?null:t.jsx(V,{title:"Target",children:t.jsx("dl",{className:"space-y-1.5",children:s.map(([n,r])=>t.jsxs("div",{className:"flex items-start justify-between gap-3 text-sm",children:[t.jsx("dt",{className:"text-text-muted capitalize min-w-0",children:n.replace(/([a-z])([A-Z])/g,"$1 $2")}),t.jsx("dd",{className:"text-text-primary font-medium text-right min-w-0 break-words",children:r})]},n))})})}const Kl=new Set(["region","Region"]),Hl=new Map([["tier","access_tier"],["sku_name","sku"],["tls_min_version","min_tls_version"],["network_acl_default_action","network_acl_default"],["encryption_at_rest","encryption_enabled"],["blob_encryption_enabled","encryption_enabled"],["public_access","public_access_enabled"],["public_blob_access","public_access_enabled"]]);function ql(e,s){const n=new Map(e);return e.filter(([r,a])=>{if(Kl.has(r))return!s;const i=Hl.get(r);return!i||!n.has(i)?!0:String(n.get(i))!==String(a)})}function Vl(e,{resourceUid:s,purchaseType:n,regionShown:r=!1}={}){const a=fn(e);return ql([...Object.entries(e??{}).filter(([i])=>i!==a),...n?[["purchase_type",n]]:[],...s?[["resource_uid",s]]:[]],r)}function me({name:e,value:s}){return t.jsxs("div",{className:"min-w-0",children:[t.jsx("span",{className:"block text-xs leading-tight text-text-muted",children:e}),t.jsx("span",{className:"block text-xs leading-tight font-medium text-text-primary break-words",children:s})]})}function gn({children:e,className:s=""}){return t.jsx("div",{className:`flex flex-col gap-2 min-w-0 ${s}`,children:e})}const Gl=6;function ws({entries:e,renderRow:s}){if(e.length===0)return null;const n=e.length>Gl;return t.jsx(gn,{className:n?"max-h-56 overflow-y-auto overscroll-contain pr-1":"",children:e.map(s)})}function Zl([e,s]){return t.jsx(me,{name:Ql(e),value:zl(e,s)},e)}function Yl([e,s]){return t.jsx(me,{name:e,value:s},e)}function Ql(e){if(Ns[e])return Ns[e];const s=String(e).replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[_-]+/g," ").trim().split(/\s+/).filter(Boolean).map(a=>/^[A-Z][a-z]+$/.test(a)?a.toLowerCase():a);if(s.length===0)return e;const[n,...r]=s;return[n.charAt(0).toUpperCase()+n.slice(1),...r].join(" ")}function Jl({rec:e,cloudAccountName:s="",trailing:n}){const r=s||e?.cloudAccountId||"",a=[s,e?.cloudAccountId].filter(Boolean).join(" · "),i=Bs(e),o=wr(e),l=Ul(e?.specs);return t.jsx(gn,{className:"flex-1",children:t.jsxs("span",{"data-testid":"rec-identity-strip",className:"contents",children:[!o&&i&&t.jsx(me,{name:"Name",value:t.jsx(nt,{uid:i,className:"text-xs min-w-0 !text-text-primary font-medium"})}),e?.resourceType&&t.jsx(me,{name:"Type",value:e.resourceType}),l&&t.jsx(me,{name:"Size",value:l}),r&&t.jsx(me,{name:"Account",value:e?.cloudAccountId?t.jsx(O,{content:a,children:t.jsx(nt,{uid:e.cloudAccountId,label:r,ariaLabel:`Copy account id ${e.cloudAccountId}`,className:"text-xs min-w-0 !text-text-primary !font-sans font-medium"})}):t.jsx(O,{content:a,onlyOnOverflow:!0,children:t.jsx("span",{className:"block truncate min-w-0",children:r})})}),n]})})}function Xl({rec:e,provider:s,cloudAccountName:n="",purchaseType:r,specsLoading:a=!1,headerAction:i=null}){const o=e?.region||null,l=e?.resourceUid,c=Vs(),[d,u]=f.useState(null);f.useEffect(()=>{if(o||!l)return;let b=!0;return c(l).then(A=>{b&&u({uid:l,region:A})}).catch(()=>{b&&u({uid:l,region:null})}),()=>{b=!1}},[o,l,c]);const m=d&&d.uid===l,x=o||(m?d.region:null),h=!o&&!!l&&!m,p=e?.specs&&Object.keys(e.specs).length>0,y=e?.resourceTags&&Object.keys(e.resourceTags).length>0;return t.jsx(V,{title:"Resource",testId:"resource-panel",headerAction:i,children:t.jsxs("div",{className:"grid grid-cols-1 gap-x-6 gap-y-6 sm:grid-cols-[repeat(auto-fit,minmax(14rem,1fr))]",children:[t.jsxs("section",{className:"space-y-1.5 min-w-0",children:[t.jsxs("p",{className:`${R.label} flex items-center gap-1.5`,children:[t.jsx(ar,{provider:s,className:"shrink-0 w-3.5 h-3.5"}),"Key detail"]}
5),t.jsx(Jl,{rec:e,cloudAccountName:n,trailing:t.jsx(me,{name:"Region",value:x||(h?t.jsx("span",{"data-testid":"region-skeleton","aria-label":"Resolving region",className:"inline-block h-3 w-20 align-middle rounded bg-border-strong/40 animate-pulse"}):t.jsx("span",{className:"text-text-muted",children:"Not available"}))})})]}),(p||a)&&t.jsxs("section",{className:"space-y-1.5 min-w-0 sm:border-l sm:border-border sm:pl-6",children:[t.jsx("p",{className:R.label,children:"Attributes"}),p?t.jsx(ws,{entries:Vl(e.specs,{resourceUid:e.resourceUid,purchaseType:r,regionShown:!!x}),renderRow:Zl}):t.jsxs("span",{"data-testid":"attributes-loading","aria-hidden":"true",className:"flex items-center gap-6",children:[t.jsx("span",{className:"inline-block h-3 w-24 rounded bg-border-strong/40 animate-pulse"}),t.jsx("span",{className:"inline-block h-3 w-16 rounded bg-border-strong/40 animate-pulse"})]})]}),y&&t.jsxs("section",{className:"space-y-1.5 min-w-0 sm:border-l sm:border-border sm:pl-6",children:[t.jsx("p",{className:R.label,children:"Tags"}),t.jsx(ws,{entries:Object.entries(e.resourceTags),renderRow:Yl})]})]})})}function ec(e){const s=se();return de({mutationFn:n=>F.patch(`/itsm/recs/${e}/ownership`,n),onSuccess:()=>{s.invalidateQueries({queryKey:Q.itsm.recTicket(e)}),xe.success("Assignee updated")},onError:n=>xe.error(n.message||"Failed to update assignee")})}function tc(e,{connected:s=!0}={}){return ce({queryKey:Q.itsm.recTicket(e),queryFn:()=>F.get(`/itsm/recs/${e}`),enabled:!!e&&s,staleTime:3e4})}function sc(e){const s=se();return de({mutationFn:n=>F.post(`/itsm/recs/${e}/tickets`,n),onSuccess:n=>{if(s.invalidateQueries({queryKey:Q.itsm.recTicket(e)}),xe.success(`Created ${n?.key??"ticket"}`),Array.isArray(n?.warnings)&&n.warnings.length>0)for(const r of n.warnings)xe.warning(r)},onError:n=>xe.error(n.message||"Failed to create Jira ticket")})}function nc(e){try{const s=JSON.parse(e?.config||"{}");return{projectKey:s.defaultProjectKey||"",issueType:s.defaultIssueType||""}}catch{return{projectKey:"",issueType:""}}}function rc({recId:e,onClose:s}){const{data:n}=ht(),[r,a]=f.useState(""),[i,o]=f.useState(""),[l,c]=f.useState({accountId:"",email:""}),[d,u]=f.useState({projects:[],issueTypes:[]}),m=Zr(),{mutate:x,isPending:h}=sc(e);f.useEffect(()=>{const j=nc(n);a(j.projectKey),o(j.issueType),n?.id&&m.mutate(n.id,{onSuccess:v=>u({projects:v?.projects??[],issueTypes:v?.issueTypes??[]})})},[n?.id]);const p=m.isPending,y=!p&&m.isError,b=p?[{value:r,label:r||"Loadingâ¦"}]:d.projects.map(j=>({value:j.key,label:j.name?`${j.key} â ${j.name}`:j.key})),A=p?[{value:i,label:i||"Loadingâ¦"}]:d.issueTypes.map(j=>({value:j.name,label:j.name})),N=j=>{j.preventDefault();const v={};r.trim()&&(v.projectKey=r.trim()),i.trim()&&(v.issueType=i.trim()),l.accountId&&(v.assigneeAccountId=l.accountId),l.email.trim()&&(v.assigneeEmail=l.email.trim()),x(v,{onSuccess:s})},k=h||p;return t.jsxs("form",{onSubmit:N,className:"space-y-4",children:[y&&t.jsx("p",{className:"text-xs text-danger-500",role:"alert",children:"Couldn't load projects and issue types from Jira â check the connection in Settings and reopen this form."}),t.jsx("p",{className:"text-xs text-text-muted -mt-1",children:"Defaults are pulled from your Jira connection â change any of them if needed."}),t.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[t.jsx(Ke,{label:"Project",children:t.jsx(Dt,{options:b,value:r,onChange:j=>a(j.target.value),disabled:k})}),t.jsx(Ke,{label:"Issue type",children:t.jsx(Dt,{options:A,value:i,onChange:j=>o(j.target.value),disabled:k})})]}),t.jsx(Ke,{label:"Assignee",children:t.jsx(zs,{integrationId:n?.id,projectKey:r,value:l.accountId,onChange:c,disabled:h})}),t.jsxs("div",{className:"flex justify-end gap-2 pt-1",children:[t.jsx(D,{variant:"secondary",size:"sm",type:"button",onClick:s,disabled:h,children:"Cancel"}),t.jsx(D,{variant:"primary",size:"sm",type:"submit",disabled:k,children:h?"Creatingâ¦":"Create ticket"})]})]})}function ac(e){const s=(e||"?").replace(/@.*/,"").split(/[\s._-]+/).filter(Boolean),n=s[0]?.[0]??"?",r=s.length>1?s[s.length-1][0]:"";return(n+r).toUpperCase()}function ic({link:e,ownership:s,recId:n,canEdit:r}){const{data:a}=ht(),i=ec(n),[o,l]=f.useState(!1),[c,d]=f.useState({accountId:"",email:""}),u=s?.assigneeEmail||"",m=e.projectKey||(e.key||"").split("-")[0],x=e.externalStatus||e.externalStatusCat,h=()=>i.mutate({assigneeAccountId:c.accountId,assigneeEmail:c.email},{onSuccess:()=>{l(!1),d({accountId:"",email:""})}}),p=()=>i.mutate({unassign:!0},{onSuccess:()=>l(!1)}),y=i.isPending,b=i.isError;return t.jsxs("div",{className:"space-y-3",children:[b&&t.jsxs("p",{className:"text-xs text-danger-500",role:"alert",children:["Couldn't update the assignee in Jira."," ",t.jsx("button",{type:"button",onClick:h,className:"underline font-medium",children:"Retry"})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",className:"inline-flex",children:t.jsxs(oe,{variant:"info",className:"gap-1",children:[e.key,t.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:2,stroke:"currentColor",className:"w-3 h-3 shrink-0",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"})})]})}),x&&t.jsx(oe,{variant:"neutral",title:e.externalStatusCat??void 0,children:x})]}),t.jsxs("div",{className:"flex items-center justify-between gap-3",children:[t.jsx("div",{className:"flex items-center gap-2 min-w-0",children:u?t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary-600/10 text-[10px] font-semibold text-primary-700",children:ac(u)}),t.jsx("span",{className:"text-sm text-text-primary truncate",children:u})]}):t.jsx("span",{className:"text-sm text-text-muted",children:"Unassigned"})}),r&&!o&&t.jsx("button",{type:"button",onClick:()=>l(!0),className:"text-xs font-medium text-primary-600 hover:underline shrink-0",children:u?"Reassign":"Assign"})]}),o&&t.jsxs("div",{className:"space-y-2 pt-0.5",children:[t.jsx(zs,{integrationId:a?.id,projectKey:m,value:c.accountId,onChange:d,disabled:y}),t.jsxs("div",{className:"flex items-center justify-end gap-2",children:[t.jsx(D,{variant:"secondary",size:"sm",type:"button",onClick:()=>l(!1),disabled:y,children:"Cancel"}),u&&t.jsx(D,{variant:"secondary",size:"sm",type:"button",onClick:p,disabled:y,children:"Clear assignee"}),t.jsx(D,{variant:"primary",size:"sm",type:"button",onClick:h,disabled:y||!c.accountId&&!c.email.trim(),children:y?"Savingâ¦":"Save"})]})]})]})}function oc(){return ir()??"jira"}const yn="zopdev_playground_sn_tickets";function wt(e){let s=0;for(let n=0;n<e.length;n++)s=s*31+e.charCodeAt(n)|0;return Math.abs(s)}function ks(){try{return JSON.parse(sessionStorage.getItem(yn)||"{}")}catch{return{}}}function bn(e){return"INC"+String(1e6+wt(e)%8999999).padStart(7,"0")}function lc(e){return wt(e).toString(16).padStart(8,"0")+"a1b2c3d4e5f6a7b8c9d0e1f2"}function cc(e,s){return`${String(e||"").replace(/\/+$/,"")}
5/nav_to.do?uri=incident.do?sys_id=${lc(s)}`}function dc(e){return wt(e)%2===0?{key:bn(e)}:null}function uc(e,s){const[,n]=f.useState(0),r=$s()&&!!e,i=(r?ks()[e]:null)||(r?dc(e):null),o=()=>{if(!r)return;const l=ks();l[e]={key:bn(e)};try{sessionStorage.setItem(yn,JSON.stringify(l))}catch{}n(c=>c+1)};return{ticket:i?{key:i.key,url:cc(s,e)}:null,create:o}}function mc({recId:e,connected:s,readOnly:n,canCreateTicket:r}){const[a,i]=f.useState(!1),{data:o,isLoading:l,isError:c,refetch:d}=tc(e,{connected:s}),u=o?.link??null;return l?t.jsxs("div",{className:"flex items-center gap-3 animate-pulse","aria-busy":"true",children:[t.jsx("div",{className:"h-4 w-4 rounded bg-surface-tertiary/40"}),t.jsx("div",{className:"h-4 flex-1 rounded bg-surface-tertiary/30"})]}):c?t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",role:"alert",children:[t.jsx("p",{className:"text-xs text-danger-500",children:"Couldn't load ticket status."}),t.jsx(D,{variant:"secondary",size:"sm",onClick:()=>d(),children:"Retry"})]}):u?t.jsx(ic,{link:u,ownership:o?.ownership,recId:e,canEdit:!n&&r}):a?t.jsx(rc,{recId:e,onClose:()=>i(!1)}):r?t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsx("p",{className:"text-xs text-text-secondary",children:"Track this recommendation in Jira."}),t.jsx(D,{variant:"secondary",size:"sm",disabled:n,onClick:()=>i(!0),children:"Create Jira ticket"})]}):t.jsx("p",{className:"text-xs text-text-muted",children:"No ticket linked."})}function xc({recId:e,instanceUrl:s,readOnly:n}){const r=uc(e,s);return r.ticket?t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("p",{className:"text-xs text-text-muted",children:"Tracked in ServiceNow"}),t.jsx("p",{className:"text-sm font-medium text-text-primary truncate",children:r.ticket.key})]}),t.jsx("a",{href:r.ticket.url,target:"_blank",rel:"noopener noreferrer",className:"text-xs font-medium text-primary-600 hover:underline shrink-0",children:"View in ServiceNow â"})]}):t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsx("p",{className:"text-xs text-text-secondary",children:"Track this recommendation in ServiceNow."}),t.jsx(D,{variant:"secondary",size:"sm",disabled:n,onClick:()=>r.create(),children:"Create ServiceNow ticket"})]})}function pc({recId:e,readOnly:s}){const n=or(lr.CLOUD_ACCOUNT_CREATE),{data:r}=ht(),a=!!r,{data:i}=Yr(),o=!!i,l=oc(),c=a&&l==="jira",d=$s()&&o&&l==="servicenow";return!c&&!d?null:t.jsx(V,{title:"Ticketing",children:c?t.jsx(mc,{recId:e,connected:a,readOnly:s,canCreateTicket:n}):t.jsx(xc,{recId:e,instanceUrl:i?.config?.instanceUrl,readOnly:s})})}function jn({onClick:e,variant:s="strip"}){if(!e)return null;const n=s==="inline";return t.jsxs("button",{type:"button",onClick:e,"data-testid":"drawer-history-link",title:"See every recommendation raised on this resource, over time","aria-label":"History",className:n?"inline-flex shrink-0 items-center gap-1 rounded text-[11px] text-text-muted transition-colors hover:text-primary-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40":"ml-auto inline-flex items-center gap-1.5 text-text-secondary hover:text-primary-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40 rounded",children:[t.jsx("svg",{className:"shrink-0",width:n?"14":"13",height:n?"14":"13",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.75,"aria-hidden":"true",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 6v6l3.5 2M3.5 12a8.5 8.5 0 1 0 2.6-6.1M3.5 4.5V9H8"})}),"History"]})}function hc({rec:e,onViewHistory:s}){const{internal:n}=ut(),r=le(e.generatedAt),a=le(e.lastReevaluatedAt||e.updatedAt);if(!r&&!a)return null;const i=e.status==="open"?ct(e.generatedAt):null,o=[];return r&&o.push(`First detected ${r}`),a&&o.push(`Last checked ${a}`),n&&e.ruleVersion&&o.push(`Raised under rule v${e.ruleVersion}`),i!==null&&o.push(i===0?"Opened today":`Open for ${i} day${i===1?"":"s"}`),t.jsxs("div",{className:"mt-1 pt-3 border-t border-border flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-text-muted",children:[o.map((l,c)=>t.jsxs("span",{className:"flex items-center gap-x-2",children:[c>0&&t.jsx("span",{"aria-hidden":"true",children:"·"}),l]},l)),t.jsx(jn,{onClick:s})]})}function fc({rec:e,isOpen:s}){const{fmtCurrency:n,fmtCurrencyCompact:r}=G(),a=Number(e?.savingsUsd??0);if(!(a>0)||!Pr(e?.status))return null;const i=typeof e?.annualSavingsUsd=="number"?e.annualSavingsUsd:null,o=dt
5(e,s),l=s?"Potential saving":o==="Saved"?"Saving from a confirmed change":"Estimated saving",c=i===null?`${l}: ${n(a)} per month`:`${l}: ${n(a)} per month · ${n(i)} per year`;return t.jsx(O,{content:c,children:t.jsxs("span",{"data-testid":"savings-chip",className:"inline-flex items-baseline gap-1.5 shrink-0 rounded-lg border border-success-500/30 bg-success-500/10 px-2.5 py-1 cursor-default",children:[t.jsx("span",{className:"text-[11px] font-medium text-success-700/80 leading-none",children:s?"Saves":o}),t.jsx("span",{className:"text-sm font-bold tabular-nums text-success-700 leading-none",children:r(a)}),t.jsx("span",{className:"text-[11px] font-medium text-success-700/80 leading-none",children:"/mo"}),i!==null&&t.jsxs("span",{className:"text-[11px] text-text-muted leading-none whitespace-nowrap",children:["· ",r(i),"/yr"]})]})})}const et=[{key:"1w",label:"1 week",days:7},{key:"1m",label:"1 month",days:30},{key:"3m",label:"3 months",days:90},{key:"6m",label:"6 months",days:180},{key:"forever",label:"Forever",days:null}],gc="1m";function Ss(e,s=new Date){return e.days===null?null:new Date(s.getTime()+e.days*864e5)}const yc=t.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2.5,"aria-hidden":"true",className:"shrink-0",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M20 6 9 17l-5-5"})}),bc=t.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,"aria-hidden":"true",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 8.25l-7.5 7.5-7.5-7.5"})}),jc="forever";function vc({disabled:e=!1,snoozeDisabled:s=!1,onDismiss:n}){const[r,a]=f.useState(s?jc:gc),[i,o]=f.useState(!1),l=f.useRef(null);f.useEffect(()=>{if(!i)return;const u=x=>{l.current&&!l.current.contains(x.target)&&o(!1)},m=x=>{x.key==="Escape"&&o(!1)};return document.addEventListener("mousedown",u),document.addEventListener("keydown",m),()=>{document.removeEventListener("mousedown",u),document.removeEventListener("keydown",m)}},[i]);const c=et.find(u=>u.key===r)??et[1],d=c.days===null?"Dismiss":`Dismiss for ${c.label}`;return t.jsxs("div",{ref:l,className:"relative inline-flex",children:[t.jsxs("div",{className:`inline-flex h-8 items-stretch rounded-lg border border-border-strong bg-surface-tertiary text-text-primary overflow-hidden ${e?"opacity-disabled":"hover:border-primary-600/20"}`,children:[t.jsx("button",{type:"button",disabled:e,"data-testid":"dismiss-snooze-action",onClick:()=>n(Ss(c)),className:"px-3 text-xs font-semibold transition-colors hover:bg-surface-elevated disabled:cursor-not-allowed focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-600/30",children:d}),!s&&t.jsxs(t.Fragment,{children:[t.jsx("span",{"aria-hidden":"true",className:"w-px self-stretch bg-border-strong"}),t.jsx("button",{type:"button",disabled:e,"aria-haspopup":"menu","aria-expanded":i,"aria-label":"Choose how long to dismiss for","data-testid":"dismiss-snooze-caret",onClick:()=>o(u=>!u),className:"px-2 flex items-center transition-colors hover:bg-surface-elevated disabled:cursor-not-allowed focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-600/30",children:bc})]})]}),i&&!s&&t.jsx("div",{role:"menu","aria-label":"Dismiss duration","data-testid":"dismiss-snooze-menu",className:"absolute right-0 bottom-full mb-1 z-50 w-64 rounded-xl border border-border-strong bg-surface-elevated shadow-xl py-1",children:et.map(u=>{const m=Ss(u),x=u.key===c.key;return t.jsxs("button",{type:"button",role:"menuitemradio","aria-checked":x,onClick:()=>{a(u.key),o(!1)},className:"w-full flex items-start gap-2 px-3 py-2 text-left transition-colors hover:bg-surface-tertiary focus:outline-none focus-visible:bg-surface-tertiary",children:[t.jsx("span",{className:`mt-0.5 ${x?"text-primary-600":"text-transparent"}`,"aria-hidden":"true",children:yc}),t.jsxs("span",{className:"min-w-0",children:[t.jsx("span",{className:"block text-sm font-medium text-text-primary",children:u.label}),t.jsx("span",{className:"block text-xs text-text-muted",children:m?`Comes back ${le(m)}`:"Never comes back on its own"})]})]},u.key)})})]})}function Nc(e,s,n){const r=[];for(const a of e??[]){const i=s?.[a.id];if(!i||i.length===0){r.push({key:`${a.id}:generated`,rec:a,at:a.generatedAt,dayKey:n(a.generatedAt),events:[],status:a.status,startStatus:a.status,continuedFrom:null});continue}const o=[...i].sort((u,m)=>Date.parse(u.at??0)-Date.parse(m.at??0)),l=new Map;for(const u of o){const m=n(u.at);l.has(m)||l.set(m,[]),l.get(m).push(u)}const c=[...l.keys()];let d=o.find(u=>u.prev_status)?.prev_status??a.status;
5c.forEach((u,m)=>{const x=l.get(u),h=d;for(const p of x)p.next_status&&(d=p.next_status);r.push({key:`${a.id}:${u}`,rec:a,at:x[x.length-1].at,dayKey:u,events:x,status:d,startStatus:h,continuedFrom:m>0?c[m-1]:null})})}return r.sort((a,i)=>{const o=Date.parse(i.at??0)-Date.parse(a.at??0);return o!==0?o:String(a.rec.id).localeCompare(String(i.rec.id))}),r}function Pe(e,s,{yearWhenDifferent:n=!0}={}){const r=Date.parse(e??"");if(Number.isNaN(r))return"â";const a=new Date(r),i={day:"numeric",month:"short",timeZone:s||void 0};return n&&Cs(a,s)!==Cs(new Date,s)&&(i.year="numeric"),a.toLocaleDateString(void 0,i)}function Cs(e,s){return e.toLocaleDateString("en-CA",{timeZone:s||void 0,year:"numeric"})}const wc={created:"Recommendation generated",viewed:"Recommendation viewed",bookmarked:"Bookmarked",unbookmarked:"Bookmark removed",applied:"Applied",auto_applied:"Applied automatically by ZopNight",dismissed:"Dismissed",reopened:"Reopened",closed:"Closed",optimised:"Marked optimised",status_changed:"Status changed",reevaluated:"Re-evaluated",drifted:"Drifted",observing:"Observing",option_chosen:"Option chosen",preview_diffed:"Change previewed",predicate_failed:"Safety check failed"},vn="system.unknown";function kt(e){return!e||e.includes("@")?!1:e==="system"||e==="engine"||e.startsWith("system.")}function kc(e){return!e||e===vn?!0:!kt(e)}function Sc(e){return!e||e===vn?"an unidentified actor":kt(e)?"ZopNight":e}function Cc(e,s){if(!s&&Or(e))return null;const n=Fr[e];return n?e==="resource_gone"?n:`Closed â ${n.charAt(0).toLowerCase()}${n.slice(1)}`:null}const _c={external:" (outside ZopNight)",zopnight_executed:" (applied by ZopNight)",zopnight_user:" (applied from ZopNight)"};function fe(e){return e==null?null:typeof e=="string"?e||null:typeof e=="number"||typeof e=="boolean"?String(e):null}function Rc(e){if(e.kind!=="reevaluated")return null;const s=fe(e.details?.want),n=fe(e.details?.after);if(!s||!n||s===n)return null;const r=fe(e.details?.before),a=fe(e.details?.target_key)??fe(e.details?.field),i=fe(e.details?.resolution_state)==="verified_reverted";return{key:a,want:s,after:n,reverted:i,moved:!r||r!==n}}function Ac(e,s=null){let n=s;return e.map(r=>{r.kind==="created"&&!n&&(n="open");const a=r.prev_status??n;return r.next_status&&(n=r.next_status),{...r,statusAtTime:a}})}function _s(e){return e.kind==="reevaluated"?e.details?.resolution_state??null:null}function Ec(e,s,n){if(e==="closed"){const r=s?.closure_reason_code;if(r){const a=Cc(r,n);if(a)return a}}if(e==="reevaluated"){const r=Br[s?.resolution_state];if(r)return r+(_c[s?.attribution]??"")}return wc[e]||e}function Tc(e,s){const n=Date.parse(e??"");return Number.isNaN(n)?"â":new Date(n).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:s||void 0})}function lt(e,s){const n=Date.parse(e??"");return Number.isNaN(n)?"unknown":new Date(n).toLocaleDateString("en-CA",{timeZone:s||void 0})}function Ic(e){const s=[];for(const n of e){const r=s[s.length-1];if(r&&kt(n.actor)&&r.event.kind===n.kind&&r.event.actor===n.actor&&r.event.prev_status===n.prev_status&&r.event.next_status===n.next_status&&r.event.details?.closure_reason_code===n.details?.closure_reason_code&&_s(r.event)===_s(n)){r.count+=1,r.lastAt=n.at;continue}s.push({event:n,count:1,lastAt:n.at})}return s}const $c=new Set(["closed","applied","auto_applied","dismissed","reopened","predicate_failed"]),Lc=new Set(["verified_diverged","verified_reverted"]);function Mc(e){return $c.has(e.kind)?!0:Lc.has(e.details?.resolution_state)}const Rs=3;function Dc(e){const s=[];for(const n of e){const r=n.event.statusAtTime??null,a=s[s.length-1];if(a&&a.status===r){a.runs.push(n);continue}s.push({status:r,runs:[n],key:`${r??"unknown"}-${n.event.id}`})}return s}function Pc(e,s){const n=new Set;let r=null;for(const a of e)for(const i of a.runs){const o=lt(i.event.at,s);o!==r&&(n.add(i.event.id),r=o)}return n}function Bc({recId:e,enabled:s=!0,events:n,seedStatus:r=null}){const a=Array.isArray(n),{data:i,isPending:o,isLoading:l,isError:c}=Ws(e,{enabled:s&&!a}),{timezone:d,fmtDate:u}=G(),{internal:m}=ut(),x=a?n:i?.items??[],h=Dc(Ic(Ac(x,r))),p=Pc(h,d),[y,b]=f.useState(()=>new Map),A=h.length===1,N=(w,M,$)=>y.get(w)??(!A&&!$&&M>Rs),k=(w,M)=>b($=>new Map($).set(w,!M)),j=h.map(w=>{const M=w.runs.reduce((g,E)=>g+E.count,0),$=w.runs.some(g=>Mc(g.event));return{group:w,count:M,collapsed:N(w.key,w.runs.length,$),foldable:w.runs.length>Rs,chip:w.status?{label:ie(w.status),variant:Ce[w.status]||"neutral"}:null}}),v=j.some(w=>w.collapsed),L=()=>b(()=>new Map(j.map(w=>[w.group.key,!v]))),U=!A&&j.some(w=>w.foldable)?t.jsxs("button",{type:"button",onClick:L,"aria-label":v?"Expand all":"Collapse all",title:v?"Expand all":"Collapse all",className:"inline-flex shrink-0 items-center gap-1 rounded p-0.5 text-[11px] text-text-muted hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40",children:[v?"Expand all":"Collapse all",t.jsx("svg",{"aria-hidden":!0,width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:v?t.jsxs(t.Fragment,{children:[t.jsx("path",{d:"M7 9l5-5 5 5"}),t.jsx("path",{d:"M7 15l5 5 5-5"})]}):t.jsxs(t.Fragment,{children:[t.jsx("path",{d:"M7 4l5 5 5-5"}),t.jsx("path",{d:"M7 20l5-5 5 5"})]})})]}):null,Z=o&&!l;return t.jsxs("div",{className:"space-y-3","data-testid":"recommendation-event-timeline",children:[l&&t.jsx("p",{className:"text-xs text-text-muted",children:"Loadingâ¦"}),c&&t.jsx("p",{className:"text-xs text-text-muted",children:"Could not load this recommendation's history."}),!o&&!c&&!Z&&x.length===0&&t.jsx("p",{className:"text-xs text-text-muted",children:"No events recorded for this recommendation."}),i?.truncated&&t.jsx("p",{className:"text-[11px] text-text-muted",children:"Showing the most recent events. Some earlier ones are not listed."}),x.length>0&&U&&t.jsx("div",{className:"flex items-center justify-end",children:U}),t.jsx("div",{className:"max-h-[60vh] space-y-3 overflow-y-auto overscroll-contain pr-1",children:j.map(({group:w,chip:M,count:$,collapsed:g},E)=>t.jsxs("section",{children:[t.jsx("div",{className:"flex items-center gap-2",children:t.jsxs("button",{type:"button",onClick:()=>k(w.key,g),"aria-expanded":!g,className:"flex min-w-0 flex-1 items-center gap-1.5 rounded py-0.5 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40",children:[t.jsx("svg",{"aria-hidden":!0,width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",className:`shrink-0 text-text-muted transition-transform ${g?"":"rotate-90"}`,children:t.jsx("path",{d:"M9 6l6 6-6 6"})}),M?t.jsx(oe,{variant:M.variant,className:"!px-1.5 !py-0 !text-[10px] !font-normal",children:M.label}):t.jsx("span",{className:"text-[11px] text-text-muted",children:"Status unknown"}),t.jsxs("span",{className:"text-[11px] text-text-muted",children:[$," event",$===1?"":"s"]})]})}),!g&&t.jsx("ol",{className:"mt-1 space-y-2",children:w.runs.map(({event:_,count:T,lastAt:W})=>t.jsxs(f.Fragment,{children:[p.has(_.id)&&t.jsxs("li",{className:"flex items-center gap-2 pt-1.5 first:pt-0","aria-hidden":"true",children:[t.jsx("span",{className:"w-14 shrink-0 text-right text-[11px] font-medium text-text-secondary",children:Pe(_.at,d)}),t.jsx("span",{className:"h-px flex-1 bg-border-strong/30"})]}),t.jsxs("li",{className:"flex gap-3",children:[t.jsx(O,{content:T>1&&W&&W!==_.at?`${u(_.at)} â ${u(W)}`:u(_.at),placement:"top",children:t.jsxs("div",{className:"w-14 shrink-0 pt-px text-right text-[11px] leading-tight text-text-muted tabular-nums",children:[Tc(_.at,d),T>1&&W&<(W,d)!==lt(_.at,d)&&t.jsxs(t.Fragment,{children:[t.jsx("br",{}),"â ",Pe(W,d)]})]})}),t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsxs("p",{className:"text-xs font-medium text-text-secondary",children:[Ec(_.kind,_.details,m),T>1&&t.jsxs("span",{className:"ml-1.5 font-normal text-text-muted",children:["Ã",T]}
5)]}),kc(_.actor)&&t.jsxs("p",{className:"break-all text-[11px] text-text-muted",children:["by ",Sc(_.actor)]}),(()=>{const z=Rc(_);return z?t.jsxs("p",{className:"text-[11px] text-text-muted",children:[z.key?`${z.key}: `:"","asked for ",t.jsx("span",{className:"text-text-secondary",children:z.want}),",",z.reverted?" reached it and is now ":z.moved?" became ":" still ",t.jsx("span",{className:"text-text-secondary",children:z.after}),z.reverted?" again":""]}):null})(),_.details?.closure_reason_code!=="resource_gone"&&_.prev_status&&_.next_status&&t.jsxs("p",{className:"text-[11px] text-text-muted",children:[ie(_.prev_status)," â ",ie(_.next_status)]})]})]})]},_.id))})]},w.key))})]})}function Oc({item:e,isCurrent:s,activityCount:n=0,fmtDate:r,timezone:a,onSelectRec:i,autoExpandActivity:o=!1}){const l=e.rec??e,[c,d]=f.useState(!!o),u=t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"flex items-start gap-2",children:t.jsxs("div",{className:"flex items-center gap-2 flex-wrap min-w-0",children:[t.jsx(oe,{variant:Ce[e.status]||"neutral",children:ie(e.status)}),t.jsx(mt,{rec:e}),t.jsx(xt,{code:l.closureReasonCode}),e.continuedFrom&&t.jsxs("span",{className:"rounded border border-border-strong/60 px-1.5 py-px text-[10px] text-text-muted",children:["continued from ",Pe(e.continuedFrom,a)]}),s&&t.jsx("span",{className:"rounded border border-primary-600/40 bg-primary-600/10 px-1.5 py-px text-[10px] font-medium text-primary-700 dark:text-primary-300",children:"Currently viewing"})]})}),t.jsx("p",{className:"mt-1.5 text-sm text-text-primary",children:l.title}),t.jsxs("div",{className:"mt-2 pt-2 border-t border-border-strong/30 flex items-center gap-2 text-[11px] text-text-muted",children:[t.jsx("span",{className:"font-mono",children:l.ruleId}),l.updatedAt&&t.jsxs(t.Fragment,{children:[t.jsx("span",{"aria-hidden":!0,children:"·"}),t.jsxs("span",{children:["Last checked ",r(l.updatedAt)]})]}),!s&&t.jsxs("span",{className:"ml-auto inline-flex items-center gap-1 text-text-secondary",children:["View",t.jsx("svg",{width:"12",height:"12",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true",className:"shrink-0",children:t.jsx("path",{fillRule:"evenodd",d:"M8.22 5.22a.75.75 0 011.06 0l4.25 4.25a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 010-1.06z",clipRule:"evenodd"})})]})]})]}),m=n>0&&t.jsxs("div",{className:`mt-2 border-t pt-2 ${s?"border-primary-600/20":"border-border-strong/30"}`,children:[t.jsxs("button",{type:"button",onClick:()=>d(x=>!x),"aria-expanded":c,className:"flex w-full items-center gap-1.5 text-left text-[11px] font-medium text-text-secondary hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40 rounded",children:[t.jsx("svg",{"aria-hidden":!0,width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",className:`shrink-0 transition-transform ${c?"rotate-90":""}`,children:t.jsx("path",{d:"M9 6l6 6-6 6"})}),"Activity (",n,")"]}),c&&t.jsx("div",{className:"mt-2",children:t.jsx(Bc,{recId:l.id,events:e.events?.length?e.events:void 0,seedStatus:e.events?.length?e.startStatus??null:null})})]});return s?t.jsxs("div",{className:"rounded-lg border border-primary-600/40 bg-primary-600/[0.04] px-3 py-2.5",children:[u,m]}):t.jsxs("div",{className:"rounded-lg border border-border-strong/60 px-3 py-2.5 transition-colors hover:border-primary-600/50 hover:bg-surface-tertiary/40",children:[t.jsx("button",{type:"button",onClick:()=>i?.(),className:"w-full rounded text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40",children:u}),m]})}function Fc(e){const s=e?.title?.trim();return s?[e.resourceName,e.resourceUid].filter(Boolean).reduce((r,a)=>{const i=String(a).replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return r.replace(new RegExp(`(^|\\s)${i}(?=\\s|$)`,"g")," ")},s).replace(/\s+/g," ").replace(/\s+([,.])/g,"$1").trim()||s:e?.ruleId??""}function Uc({value:e}){const[s,n]=f.useState(!1),r=async()=>{try{await navigator.clipboard.writeText(e),n(!0),setTimeout(()=>n(!1),1500)}catch{}};return t.jsxs("button",{type:"button",onClick:r,"data-testid":"history-copy-identifier","aria-label":`Copy ${e}`,title:s?"Copied":"Copy",className:"group inline-flex min-w-0 items-baseline gap-1 rounded text-left font-medium text-text-primary transition-colors hover:text-primary-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40 dark:hover:text-primary-300",children:[t.jsx("span",{className:"break-all",children:e}
5),t.jsx("span",{"aria-hidden":!0,className:"shrink-0 text-[10px] text-text-muted opacity-0 transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100",children:s?"â":"â§"}),t.jsx("span",{className:"sr-only",role:"status",children:s?"Copied":""})]})}function zc({open:e,onClose:s,rec:n,currentRecId:r,onSelectRec:a,autoExpandActivity:i=!1}){const{fmtDate:o,timezone:l}=G(),{data:c,isPending:d,isError:u}=Jr(n?.resourceUid,{enabled:!!(e&&n?.resourceUid)}),m=(c??[]).map(S=>S.id).filter(Boolean),{data:x,isLoading:h}=Xr(m,{enabled:!!e}),y=Nc(c??[],x,S=>{const C=Date.parse(S??"");return Number.isNaN(C)?"unknown":new Date(C).toLocaleDateString("en-CA",{timeZone:l||void 0})}),[b,A]=f.useState(null),N=[],k=new Set;for(const S of y){const C=S.rec??S,P=C.ruleId;P&&!k.has(P)&&(k.add(P),N.push({value:P,label:Fc(C),sublabel:P}))}N.sort((S,C)=>S.label.localeCompare(C.label));const j=y.map(S=>S.rec??S).find(S=>S.id===(r??n?.id))?.ruleId??n?.ruleId??"",v=j&&k.has(j)?j:"",L=(b===null?v:b).split(",").filter(S=>k.has(S)),U=L.join(","),Z=U===v,w=N.length>0&&L.length===N.length,M=L.length?y.filter(S=>L.includes((S.rec??S).ruleId)):y,$=Kc(M,l),g=[],E=new Set;for(const S of $.flatMap(C=>C.items)){const C=S.rec??S;C?.id&&!E.has(C.id)&&(E.add(C.id),g.push(C))}const _=r??n?.id,{data:T}=Ws(_,{enabled:!!(e&&_)}),z=(T?.items??[]).length,H=S=>(S.rec?.id??S.id)===(r??n?.id);return e?t.jsxs(be,{open:e,onClose:s,title:"Recommendation history",subtitle:t.jsxs("span",{className:"flex min-w-0 items-baseline gap-1.5",children:[n?.resourceType&&t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"shrink-0",children:n.resourceType}),t.jsx("span",{"aria-hidden":!0,className:"shrink-0",children:"·"})]}),t.jsx(Uc,{value:n?.resourceName||n?.resourceUid||"this resource"})]}),children:[t.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-3",children:[N.length>1&&t.jsx("div",{"data-testid":"history-rule-filter",className:"min-w-[16rem] flex-1",children:t.jsx(Qr,{multi:!0,options:N,triggerLabel:"Filter by rule",searchPlaceholder:"Search rules",footer:t.jsx("button",{type:"button","data-testid":"history-rule-select-all",onClick:()=>A(w?"":N.map(S=>S.value).join(",")),className:"w-full px-3 py-2 text-left text-xs font-medium text-text-secondary hover:bg-surface-tertiary hover:text-text-primary transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-600/40",children:w?"Clear selection":"Select all"}),value:U,onChange:S=>A(S.target.value),placeholder:"All rules",size:"sm",portal:!0,multiline:!0,stopEscapePropagation:!0})}),N.length>1&&!Z&&t.jsx("div",{className:"ml-auto flex shrink-0 items-center gap-2",children:t.jsx("button",{type:"button","data-testid":"history-filter-reset",onClick:()=>A(null),className:"shrink-0 inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-text-muted hover:text-text-primary rounded-md transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40",children:"Reset"})})]}),t.jsx("div",{className:"space-y-4","data-testid":"recommendation-timeline",children:t.jsxs("div",{"data-testid":"resource-recommendation-history",children:[(d||h)&&t.jsx(Wc,{}),u&&t.jsx("p",{className:"text-xs text-text-muted",children:"Could not load this resource's history."}),!d&&!h&&!u&&$.length===0&&t.jsx("p",{className:"text-xs text-text-muted",children:"No recommendation history for this resource yet."}),$.map(({label:S,items:C})=>t.jsxs("section",{children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("h3",{className:"text-xs font-semibold text-text-secondary whitespace-nowrap",children:S}),t.jsx("span",{"aria-hidden":!0,className:"h-px flex-1 bg-border-strong/50"})]}),t.jsx("ul",{className:"mt-2 space-y-2",children:C.map((P,Fe)=>t.jsxs("li",{className:"flex gap-3",children:[t.jsx("div",{className:"w-14 shrink-0 pt-3 text-right text-[11px] leading-tight text-text-muted",children:Pe(P.at??P.generatedAt,l,{yearWhenDifferent:!1})}),t.jsxs("div",{className:"relative flex-1 min-w-0 pl-5",children:[t.jsx("span",{"aria-hidden":!0,className:`absolute left-[3px] top-0 w-px bg-border-strong/50 ${Fe===C.length-1?"bottom-0":"-bottom-2"}`}
5),t.jsx("span",{"aria-hidden":!0,className:`absolute left-0 top-[15px] h-2 w-2 rounded-full ring-2 ring-surface-primary ${P.status==="open"?"bg-warning-500":"bg-text-muted"}`}),t.jsx(Oc,{item:P,activityCount:P.events?.length||(H(P)?z:0),isCurrent:H(P),timezone:l,autoExpandActivity:i&&(P.rec?.id??P.id)===(r??n?.id),fmtDate:o,onSelectRec:()=>a?.(P.rec??P,{items:g,index:g.findIndex(Y=>Y.id===(P.rec?.id??P.id))})})]})]},P.key??P.id))})]},S)),$.length>0&&t.jsx("p",{className:"mt-4 border-t border-border-strong/40 pt-3 text-[11px] leading-relaxed text-text-muted",children:"Each card is one recommendation on one day â dated by what happened that day, showing the status it ended that day in. Open Activity on a card for exact times, including when it closed."})]})})]}):null}function Wc(){return t.jsxs("div",{className:"mt-2","data-testid":"history-skeleton",children:[t.jsx("span",{className:"sr-only",role:"status",children:"Loading this resource's recommendation historyâ¦"}),t.jsxs("div",{"aria-hidden":!0,className:"animate-pulse",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("span",{className:"h-3 w-24 rounded bg-border-strong/40"}),t.jsx("span",{className:"h-px flex-1 bg-border-strong/30"})]}),t.jsx("ul",{className:"mt-2 space-y-2",children:[0,1,2].map(e=>t.jsxs("li",{className:"flex gap-3",children:[t.jsx("div",{className:"w-14 shrink-0 pt-3 text-right",children:t.jsx("span",{className:"ml-auto block h-3 w-10 rounded bg-border-strong/40"})}),t.jsxs("div",{className:"relative min-w-0 flex-1 pl-5",children:[t.jsx("span",{className:"absolute bottom-0 left-[3px] top-0 w-px bg-border-strong/50"}),t.jsx("span",{className:"absolute left-0 top-[15px] h-2 w-2 rounded-full bg-border-strong/60 ring-2 ring-surface-primary"}),t.jsxs("div",{className:"rounded-lg border border-border-strong/40 p-3",children:[t.jsx("span",{className:"block h-4 w-16 rounded bg-border-strong/40"}),t.jsx("span",{className:"mt-2 block h-3.5 w-full rounded bg-border-strong/30"}),e===0&&t.jsx("span",{className:"mt-1.5 block h-3.5 w-2/3 rounded bg-border-strong/30"}),t.jsx("span",{className:"mt-2.5 block h-3 w-2/5 rounded bg-border-strong/30"})]})]})]},e))})]})]})}function Kc(e,s){const n=e.map(a=>{const i=Date.parse(a.at??a.generatedAt??"");return{rec:a,time:Number.isNaN(i)?null:i}});n.sort((a,i)=>a.time===i.time?0:a.time===null?1:i.time===null?-1:i.time-a.time);const r=[];for(const{rec:a,time:i}of n){const o=i===null?"Date unknown":new Date(i).toLocaleDateString(void 0,{month:"long",year:"numeric",timeZone:s||void 0}),l=r[r.length-1];l&&l.label===o?l.items.push(a):r.push({label:o,items:[a]})}return r}const Hc=[/^ZopNight does not\b/i,/^Note:\s/i];function qc(e){return Hc.some(s=>s.test(e))}function Nn(e){return!e||typeof e!="string"?e:e.replace(/\r/g,"").replace(/\s*[â¢Â·;]\s*(?=\d{1,2}[.)]\s)/g,` 6`).replace(/([.)\]])\s+(?=\d{1,2}[.)]\s)/g,`$1 7`)}function wn(e){if(!e||typeof e!="string")return{intro:[],steps:[],footer:[]};const s=Nn(e).split(` 8`).map(c=>c.trim()).filter(Boolean),n=/^\d+[.):]/,r=/^\d+[.):\s]+/,a=[],i=[],o=[];let l="intro";for(const c of s){if(l==="footer"){o.push(c);continue}if(n.test(c)){l="steps",i.push({body:c.replace(r,"").trim(),extra:[]});continue}if(l==="intro"){a.push(c);continue}if(qc(c)){l="footer",o.push(c);continue}i[i.length-1].extra.push(c)}return{intro:a,steps:i,footer:o}}function Vc({text:e}){if(!e)return t.jsx("p",{className:"text-sm text-text-muted italic",children:"No remediation steps provided."});const{intro:s,steps:n,footer:r}=wn(e);if(n.length===0){const a=[...s,...r];return t.jsx("ul",{className:"space-y-2",children:a.map((i,o)=>t.jsxs("li",{className:"flex gap-2 text-sm text-text-secondary leading-relaxed",children:[t.jsx("span",{className:"text-primary-500 mt-0.5 shrink-0",children:"â¢"}),t.jsx("span",{children:i})]},o))})}return t.jsxs("div",{className:"space-y-3",children:[s.map((a,i)=>t.jsx("p",{className:"text-sm text-text-primary leading-relaxed",children:a},`intro-${i}`)),t.jsx("ol",{className:"space-y-2.5","data-testid":"how-to-fix-steps",children:n.map((a,i)=>t.jsxs("li",{className:"flex gap-3",children:[t.jsx("span",{className:"shrink-0 mt-0.5 w-
85 h-5 rounded-full bg-primary-600/10 text-primary-600 text-xs font-semibold inline-flex items-center justify-center tabular-nums",children:i+1}),t.jsxs("div",{className:"min-w-0 text-sm text-text-secondary leading-relaxed",children:[t.jsx("span",{className:"text-text-primary",children:a.body}),a.extra.length>0&&t.jsx("ul",{className:"mt-1.5 space-y-1",children:a.extra.map((o,l)=>t.jsxs("li",{className:"flex gap-2 text-text-secondary",children:[t.jsx("span",{className:"text-text-muted mt-0.5 shrink-0",children:"â"}),t.jsx("span",{children:o})]},l))})]})]},`step-${i}`))}),r.length>0&&t.jsx("div",{className:"pt-2 border-t border-border-strong/40 space-y-1",children:r.map((a,i)=>t.jsx("p",{className:"text-xs text-text-muted leading-relaxed italic",children:a},`footer-${i}`))})]})}function Be(e){if(e.provider)return e.provider;const s=e.ruleId||"";return/^RC-21[01]\d$/.test(s)?"snowflake":s.startsWith("RC-1")?"gcp":s.startsWith("RC-2")||s.startsWith("AZ-")?"azure":"aws"}function kn(){return t.jsx(O,{content:"ZopNight can run a verified workflow to fix this recommendation",children:t.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs font-medium border bg-success-400/10 text-success-700 border-success-400/30",children:[t.jsx("span",{"aria-hidden":!0,className:"h-1.5 w-1.5 rounded-full bg-success-600"}),"Auto-remediation"]})})}const As={open:"awaiting your review",applied:"you applied this recommendation",dismissed:"you dismissed this recommendation",optimised:"auto-dismissed because it became stale",rule_retired:"withdrawn because the rule that produced it was removed"};function Es({dir:e,onClick:s,disabled:n,groupNoun:r="resource"}){const a=e==="prev";return t.jsx("button",{type:"button",onClick:s,disabled:n,"aria-label":`${a?"Previous":"Next"} ${r}`,title:`${a?"Previous":"Next"} ${r}`,className:"h-8 w-8 inline-flex items-center justify-center rounded-md text-text-muted hover:text-text-secondary hover:bg-surface-tertiary transition-colors duration-fast disabled:opacity-30 disabled:hover:bg-transparent",children:t.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor",className:"h-4 w-4",children:a?t.jsx("path",{fillRule:"evenodd",d:"M14.78 5.22a.75.75 0 010 1.06L11.06 10l3.72 3.72a.75.75 0 11-1.06 1.06l-4.25-4.25a.75.75 0 010-1.06l4.25-4.25a.75.75 0 011.06 0z",clipRule:"evenodd"}):t.jsx("path",{fillRule:"evenodd",d:"M8.22 5.22a.75.75 0 011.06 0l4.25 4.25a.75.75 0 010 1.06l-4.25 4.25a.75.75 0 01-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 010-1.06z",clipRule:"evenodd"})})})}const Ts=new Intl.NumberFormat,Gc={recommendation:"Rec",resource:"Resource",history:"History"};function Sn({axis:e}){if(!e?.enabled)return null;const s=e.noun,n=e.total>0&&e.position>0;return n&&e.total<=1||!n&&!e.canPrev&&!e.canNext?null:t.jsxs("div",{className:"shrink-0 inline-flex items-center gap-0.5",children:[t.jsx(Es,{dir:"prev",groupNoun:s,disabled:!e.canPrev,onClick:e.onPrev}),n&&t.jsxs("span",{className:"px-1 text-[11px] text-text-secondary whitespace-nowrap",children:[t.jsxs("span",{className:"hidden sm:inline",children:[st(s)," "]}),t.jsxs("span",{className:"sm:hidden",children:[Gc[s]??st(s)," "]}),t.jsx("span",{className:"tabular-nums",children:Ts.format(e.position)}),t.jsx("span",{className:"hidden sm:inline",children:" of "}),t.jsx("span",{className:"sm:hidden text-text-muted",children:"/"}),t.jsx("span",{className:"tabular-nums",children:Ts.format(e.total)})]}),t.jsx(Es,{dir:"next",groupNoun:s,disabled:!e.canNext,onClick:e.onNext})]})}function tt({tip:e,busy:s,onClick:n,icon:r,children:a}){return t.jsx(O,{content:e,placement:"top",children:t.jsxs("button",{className:"h-8 px-2.5 inline-flex items-center gap-1.5 rounded-lg text-xs font-medium text-text-secondary bg-surface-tertiary/40 border border-border-strong hover:border-primary-600/40 hover:text-primary-600 transition-colors disabled:opacity-40",disabled:s,onClick:n,children:[s?t.jsx("span",{className:"w-4 h-4 block border-[1.5px] border-current border-t-transparent rounded-full animate-spin"}):r,a]})})}const Zc=t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"w-4 h-4",children:[t.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),t.jsx("line",{x1:"3",y1:"9",x2:"21",y2:"9"}),t.jsx("line",{x1:"9",y1:"21",x2:"9",y2:"9"})]}),Yc=t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"w-4 h-4",children:[t.jsx("circle",{cx:"12",cy:"12",r:"10"}),t.jsx("circle",{cx:"12",cy:"12",r:"6"}),t.jsx("circle",{cx:"12",cy:"12",r:"2"})]}),Qc=t.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:"w-4 h-4",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M7.217 10.9
807a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z"})});function Jc({rec:e,isOpen:s,pending:n,readOnly:r,canUpdate:a,canShare:i,onShare:o,onApply:l,onDismiss:c,onReopen:d,actionDisabledReason:u,hideViewArchitecture:m,navigatingToCanvas:x,navigatingToBlast:h,onViewInCanvas:p,onReviewImpact:y,remediationGate:b,provider:A}){return t.jsxs("div",{className:"flex flex-wrap items-center gap-x-2 gap-y-2 w-full",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 sm:border-r sm:border-border sm:pr-2 sm:mr-1",children:[!m&&t.jsx(tt,{tip:"See this resource in the architecture map",busy:x,onClick:p,icon:Zc,children:"Architecture"}),t.jsx(tt,{tip:"See what else this change could affect",busy:h,onClick:y,icon:Yc,children:"Blast radius"}),i&&t.jsx(tt,{tip:"Share this recommendation",onClick:()=>o(e),icon:Qc,children:"Share"})]}),s&&t.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-2 ml-auto min-w-0",children:[t.jsx(O,{content:u,wrapDisabled:!0,placement:"top",children:t.jsx(vc,{snoozeDisabled:ye(e),disabled:n||r||!a,onDismiss:N=>{X(ee.RECOMMENDATION_DISMISSED,{rule_id:e.ruleId,dismiss_duration_days:N?Math.round((N.getTime()-Date.now())/864e5):null}),c(e.id,N?N.toISOString():null)}})}),t.jsx(O,{content:u,wrapDisabled:!0,placement:"top",children:t.jsx(D,{variant:"secondary",size:"compact",disabled:n||r||!a,onClick:()=>{X(ee.RECOMMENDATION_RESOLVED,{rule_id:e.ruleId,category:pt(e),provider:Be(e)}),l(e.id)},children:"Mark Resolved"})}),Hs(e)?t.jsx(Fa,{rec:e,readOnly:r,disabled:n||!r&&(!a||b.gated),disabledReason:!r&&!a?"You don't have permission. Contact your admin.":!r&&b.gated?b.reason:""}):Va(e)?t.jsx(ei,{rec:e,readOnly:r,disabled:n||!r&&!a,disabledReason:!r&&!a?"You don't have permission. Contact your admin.":""}):t.jsx(ni,{rec:e,provider:A,disabled:n})]}),!s&&t.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-2 ml-auto min-w-0",children:[t.jsx(oe,{variant:Ce[e.status]||"neutral",children:ie(e.status)}),t.jsx(mt,{rec:e}),(e.status==="applied"||e.status==="dismissed")&&Ur(e)&&a&&!r&&t.jsx(D,{variant:"secondary",size:"compact",disabled:n,onClick:()=>d(e.id),title:"Move this recommendation back to Open",children:"Reopen"})]})]})}function Xc({rec:e,category:s,isOpen:n,ruleNav:r}){return t.jsxs("div",{className:"space-y-2.5",children:[t.jsxs("div",{className:"flex items-center justify-between gap-x-3",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-x-2 gap-y-1.5 min-w-0",role:"group","aria-label":"Recommendation classification",children:[e.ruleId&&t.jsx("span",{className:"font-mono text-xs text-text-muted truncate",children:e.ruleId}),t.jsx(O,{content:`Status: ${ie(e.status)}${As[e.status]?` (${As[e.status]})`:""}`,children:t.jsx("span",{className:"inline-flex shrink-0",children:t.jsx(oe,{variant:Ce[e.status]||"neutral",children:ie(e.status)})})}),t.jsx(Ji,{rec:e}),t.jsx(mt,{rec:e}),t.jsx(xt,{code:e.closureReasonCode}),t.jsx(fc,{rec:e,isOpen:n}),t.jsx(Fs,{confidence:e.confidence,description:ho(e)}),t.jsx(Us,{category:s,rec:e}),e.watchGates?.length?t.jsx(Rl,{gates:e.watchGates}):null,Hs(e)&&t.jsx(kn,{})]}),t.jsx(Sn,{axis:r})]}),t.jsx(ta,{rec:e,className:`${R.title} max-w-2xl min-w-0`})]})}function ed({autoExpandActivity:e=!1,rec:s,onClose:n,historyOpen:r,onHistoryOpenChange:a,onApply:i,onDismiss:o,onReopen:l,onShare:c,isPending:d,canUpdate:u=!0,canShare:m=!1,accountNameMap:x={},specsLoading:h=!1,detailError:p=!1,onRetryDetail:y,hideViewArchitecture:b=!1,onBlastRadius:A,readOnly:N=!1,recList:k=[],onSelectRec:j,groupNoun:v="resource",onNavigateGroup:L,canGroupPrev:U=!1,canGroupNext:Z=!1,groupPosition:w=0,groupTotal:M=0,navigatingGroup:$=!1}){const g=Is(),[E]=f.useState(()=>Math.floor(Date.now()/1e3)),{timezone:_}=f.useContext(Se),[T,W]=f.useState(!1),z=r??T,H=a??W,[S,C]=f.useState(null),P=S?.id===s?.id?S:null,Fe=C,[Y,_e]=f.useState(null),ve=Y!==null&&Y.items.some(B=>
8B.id===s?.id),Cn=()=>{_e(null),H(!0)},St=B=>{if(!ve)return;const I=Y.index+B,ne=Y.items[I];ne&&(_e({...Y,index:I}),j?.(ne))},[Ct,_t]=f.useState(!1),[Rt,At]=f.useState(!1),[Ue,_n]=f.useState({recId:null,optionId:null}),Et=Vs(),{data:Re}=fr(s?.resourceUid?[s.resourceUid]:[]),Rn=f.useMemo(()=>{const B=Re?.items??(Array.isArray(Re)?Re:[]);for(const I of B)if(I.purchaseType&&I.purchaseType!=="OnDemand")return I.purchaseType;return null},[Re]),An=si({cloudAccountId:s?.cloudAccountId,provider:s?Be(s):null,resourceType:s?.resourceType,feature:"remediation"});if(!s)return null;const ae=s.status==="open",En=d,ze=Be(s),Tn=N?"Read-only. This is the customer's view; actions run from the customer's own account.":u?"":"You don't have permission. Contact your admin.",K=pt(s),In=s.currentCostUsd>0||s.savingsUsd>0,$n=x[s.cloudAccountId]||"",pe=To(s,K),Ln=pe.length?pe[pe.length-1].id:null,Tt=Ue.recId===s.id&&Ue.optionId?Ue.optionId:Ln,Mn=pe.find(B=>B.id===Tt)??null,We=ae&&pe.length>0,It=v==="rule",te=k.findIndex(B=>B.id===s.id),$t={enabled:!!L,position:w,total:M,canPrev:U&&!$,canNext:Z&&!$,onPrev:()=>L?.(-1),onNext:()=>L?.(1)},Lt={enabled:te>=0&&k.length>1,position:te+1,total:k.length,canPrev:te>0,canNext:te>=0&&te<k.length-1,onPrev:()=>te>0&&j?.(k[te-1]),onNext:()=>te>=0&&te<k.length-1&&j?.(k[te+1])},Dn=(ve?{enabled:!0,noun:"history",position:Y.index+1,total:Y.items.length,canPrev:Y.index>0,canNext:Y.index<Y.items.length-1,onPrev:()=>St(-1),onNext:()=>St(1)}:null)??{...It?Lt:$t,noun:"resource"},Pn=ve?{enabled:!1}:{...It?$t:Lt,noun:"recommendation"},Bn=async()=>{if(Ct)return;_t(!0);const B=new URLSearchParams;s.provider&&B.set("provider",s.provider),s.cloudAccountId&&B.set("account",s.cloudAccountId),B.set("resourceId",s.resourceUid),B.set("from","recommendations");let I=s.region;if(!I)try{I=await Et(s.resourceUid)}catch{}I&&B.set("region",I),g(`/architecture/canvas?${B.toString()}`,{state:{fromInternal:!0}}),_t(!1)},On=async()=>{if(Rt)return;At(!0);const B=Ye(K),I=new URLSearchParams;s.provider&&I.set("provider",s.provider),s.cloudAccountId&&I.set("account",s.cloudAccountId),I.set("resourceId",s.resourceUid),I.set("from","recommendations"),I.set("blastRadius","true"),I.set("blastOperation",B),s.id&&I.set("recId",s.id),s.title&&I.set("recTitle",s.title),K&&I.set("recCategory",K),s.savingsUsd&&I.set("recSavings",String(s.savingsUsd));let ne=s.region;if(!ne)try{ne=await Et(s.resourceUid)}catch{}ne&&I.set("region",ne),g(`/architecture/canvas?${I.toString()}`,{state:{fromInternal:!0}}),At(!1)},Mt=()=>{X(ee.BLAST_RADIUS_VIEWED,{entity_type:"resource",operation:Ye(K),rule_id:s.ruleId}),A?(A(s.resourceUid,Ye(K),s),n()):On()},Fn=ve?void 0:()=>{Fe(s),H(!0)},Un=t.jsx(Xc,{rec:s,category:K,isOpen:ae,ruleNav:Pn}),zn=!!s.recommendation&&s.recommendation.trim()===(s.remediation||"").trim(),Wn=s.remediationKind!=="auto"&&s.remediationKind!=="guided"&&K!=="schedule"&&!zn;return t.jsxs(t.Fragment,{children:[t.jsx(be,{open:!0,wide:!0,onClose:()=>{_e(null),n?.()},onCloseButton:ve?Cn:void 0,title:"Recommendation",footer:t.jsxs("div",{className:"w-full flex flex-col gap-2.5",children:[ae&&t.jsx(Ol,{rec:s,category:K,onBlastRadius:Mt}),t.jsx(Jc,{rec:s,isOpen:ae,pending:En,readOnly:N,canUpdate:u,canShare:m,onShare:c,onApply:i,onDismiss:o,onReopen:l,actionDisabledReason:Tn,hideViewArchitecture:b,navigatingToCanvas:Ct,navigatingToBlast:Rt,onViewInCanvas:Bn,onReviewImpact:Mt,remediationGate:An,provider:ze})]}),children:t.jsxs("div",{className:"relative",children:[$&&t.jsx("div",{className:"absolute inset-x-0 -top-2 h-0.5 overflow-hidden rounded-full bg-primary-500/15 z-20","aria-hidden":!0,children:t.jsx("span",{className:"animate-indeterminate-bar rounded-full bg-primary-500"})}),t.jsxs("div",{className:`space-y-4 transition-opacity duration-150 ${$?"opacity-50":""}`,children:[Un,p&&t.jsxs("div",{role:"alert",className:"flex flex-wrap items-center justify-between gap-3 rounded-lg border border-danger-500/30 bg-danger-500/5 p-3",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("p",{className:"text-sm font-medium text-text-primary",children:"Couldn't load the full details for this recommendation"}),t.jsx("p",{className:"mt-0.5 text-xs text-text-secondary",children:"Evidence, the proposed target and the options below may be missing or incomplete. Everything else on this page is up to date."})]}),y&&t.jsx(D,{variant:"secondary",size:"sm",onClick:()=>y(),children:"Retry"})]}),Za(s)&&t.jsxs("div",{className:"rounded-lg border border-warning-400/30 bg-warning-400/10 p-3 text-sm text-text-secondary",role:"note",children:[t.jsx("p",{className:"font-medium text-text-primary",children:"Insufficient data for optimal schedule recommendation"}),t.jsx("p",{className:"mt-0.5",children:"This resource does not currently have enough historical usage data or recurring idle periods to generate a reliable schedule."})]}),s.watchGates?.length?t.jsx(Al,{gates:s.watchGates}):null,t.jsxs("div",{className:"space-y-4",children:[t.jsx(gl,{rec:s}),t.jsx(Xl,{rec:s,provider:ze,cloudAccountName:$n,purchaseType:Rn,specsLoading:h,headerAction:t.jsxs("span",{className:"flex items-center gap-3",children:[!ye(s)&&t.jsx(jn,{variant:"inline",onClick:Fn}),t.jsx(Sn,{axis:Dn})]})}),t.jsx(fl,{rec:s}),t.jsx(bl,{rec:s,nowSec:E},`evidence-${s.id}`),ye(s)&&t.jsx(V,{title:"Policy",children:t.jsx(kl,{rec:s})},`policy-${s.id}`),(s.status==="applied"||s.status==="optimised"||ae&&K!=="schedule")&&t.jsx(Hi,{rec:s,isOpen:ae,category:K,hasCost:In,option:We?Mn:null}),t.jsx(Zi,{rec:s},s.id),We&&t.jsx(co,{options:pe,selectedId:Tt,onSelect:B=>_n({recId:s.id,optionId:B})}),ae&&t.jsx(ko,{rec:s,category:K}),(()=>{const B=Oe(s,_),I=B!==null&&nn(s)===null,ne=vt(s,E)&&!I;return(K==="schedule"||B!==null)&&!I&&!ne?t.jsx(en,{rec:s},`live-metrics-${s.id}`):null})(),Wn&&t.jsx(V,{title:"How to Fix",collapsible:!0,defaultOpen:!0,children:t.jsx(Vc,{text:s.remediation})}),!We&&t.jsx(Wl,{targetSpec:s.targetSpec}),s.tierRates&&t.jsx(hi,{recommendation:s,provider:ze}),!ye(s)&&t.jsx(pc,{recId:s.id,readOnly:N},`ticketing-${s.id}`)]}),ae&&K==="schedule"&&t.jsx(Ai,{rec:s}),t.jsx(hc,{rec:s})]})]})}),t.jsx(zc,{autoExpandActivity:e,open:z,onClose:()=>H(!1),rec:P??s,currentRecId:s?.id,onSelectRec:(B,I)=>{_e(I?{items:I.items,index:I.index}:null),H(!1),j?.(B)}})]})}const Td=Object.freeze(Object.defineProperty({__proto__:null,AutoRemediationPill:kn,CategoryPill:zr,CategoryTag:Us,ClosureReasonPill:xt,ConfidenceMeter:Wr,ConfidencePill:Fs,RecommendationDrawer:ed,STATUS_LABELS:Kr,STATUS_VARIANT:Ce,SeverityPill:Hr,capitalize:st,consoleLabelFor:qs,normalizeRemediation:Nn,parseRemediationSteps:wn,resolveCategory:pt,resolveProvider:Be,statusLabel:ie},Symbol.toStringTag,{value:"Module"}));
8export{kn as A,Rl as G,ed as R,Rd as S,La as a,Ad as b,Ed as c,Yi as d,Vs as e,Gt as f,Td as g,Hs as i,Be as r,Ra as s,$a as u};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.