import { useEffect, useMemo, useState } from "react";
import { commandIds } from "@commands/ids";
import type { ImageDocument } from "@core/document";
import type { SelectionState } from "@editor/state";
import type { AppStore } from "@editor/store";
import type { GenerateSettings } from "@editor/tools";
import { runInpaintRegionOperation } from "@operations/masks/rasterActions";
import { createNormalizedMaskSource } from "@platform/browser/maskRaster";

type ProcessedMasks = { edit: string; noise: string; blend: string; coverage: number; bounds?: { x: number; y: number; w: number; h: number } };

export function InpaintRegionPanel({ document, selection, settings, dispatch }: { document: ImageDocument; selection: SelectionState; settings: GenerateSettings; dispatch: AppStore["dispatch"] }) {
  const targetLayerId = selection.layerIds.length === 1 ? selection.layerIds[0] : undefined;
  const region = document.inpaintRegions.find((candidate) => candidate.targetLayerId === targetLayerId && candidate.enabled);
  const asset = region ? document.assets.find((candidate) => candidate.id === region.maskAssetId) : undefined;
  const [processed, setProcessed] = useState<ProcessedMasks>();
  const [busy, setBusy] = useState(false);
  const processingKey = useMemo(() => asset ? [asset.source, settings.inpaint.maskExpand, settings.inpaint.maskFeather, settings.inpaint.maskBlur, settings.inpaint.maskDespeckle].join(":") : "", [asset, settings.inpaint]);

  useEffect(() => {
    if (!asset) {
      setProcessed(undefined);
      return;
    }
    let cancelled = false;
    const width = Math.max(1, Math.round(asset.intrinsicSize.w));
    const height = Math.max(1, Math.round(asset.intrinsicSize.h));
    void Promise.all([
      createNormalizedMaskSource(asset.source, width, height, { polarity: "revealed", despeckle: settings.inpaint.maskDespeckle }),
      createNormalizedMaskSource(asset.source, width, height, { polarity: "revealed", expand: settings.inpaint.maskExpand, blur: settings.inpaint.maskBlur, despeckle: settings.inpaint.maskDespeckle }),
      createNormalizedMaskSource(asset.source, width, height, { polarity: "revealed", feather: settings.inpaint.maskFeather, despeckle: settings.inpaint.maskDespeckle }),
    ]).then(([edit, noise, blend]) => {
      if (cancelled) return;
      const active = edit.values.reduce((sum, value) => sum + value / 255, 0);
      setProcessed({ edit: edit.source, noise: noise.source, blend: blend.source, coverage: active / edit.values.length, bounds: edit.bounds });
    }).catch(() => !cancelled && setProcessed(undefined));
    return () => { cancelled = true; };
  }, [processingKey, asset, settings.inpaint.maskDespeckle, settings.inpaint.maskExpand, settings.inpaint.maskBlur, settings.inpaint.maskFeather]);

  if (!targetLayerId) return <p className="rounded-md bg-amber-300/[0.07] px-2.5 py-2 text-xs text-amber-100/70">Select one image or raster layer to create an AI edit region.</p>;
  if (!region || !asset) return <p className="rounded-md bg-white/[0.04] px-2.5 py-2 text-xs text-white/55">No AI edit region yet. Use <strong className="text-white/80">Add region</strong> beside Generate, then paint where pixels should be replaced.</p>;

  const operation = async (type: "invert" | "clear" | "fill") => {
    setBusy(true);
    try {
      await runInpaintRegionOperation(region.id, asset, type === "invert" ? { type: "invert" } : { type: "fill", fill: type === "fill" ? "white" : "black" }, dispatch);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="grid gap-2 rounded-lg border border-white/[0.07] bg-white/[0.025] p-2.5">
      <div className="flex items-center justify-between gap-2">
        <div><strong className="block text-xs text-white/80">AI edit region</strong><span className="text-[0.68rem] text-white/40">Painted pixels are replaced; unpainted pixels are protected.</span></div>
        <button type="button" className="rounded-md bg-sky-300 px-2.5 py-1 text-xs font-semibold text-slate-950" onClick={() => dispatch(commandIds.toolEnterInpaintRegionEdit, { targetLayerId, regionId: region.id })}>Edit</button>
      </div>
      {processed ? (
        <div className="grid grid-cols-3 gap-2 text-center text-[0.65rem] text-white/45">
          <MaskPreview label="Edit" source={processed.edit} />
          <MaskPreview label="Noise" source={processed.noise} />
          <MaskPreview label="Blend" source={processed.blend} />
        </div>
      ) : <span className="text-xs text-white/35">Preparing mask previews…</span>}
      <div className="flex flex-wrap items-center gap-1.5 text-[0.68rem] text-white/45">
        {processed ? <span className="mr-auto">Replace {Math.round(processed.coverage * 100)}%{processed.bounds ? ` · ${Math.round(processed.bounds.w)}×${Math.round(processed.bounds.h)} px` : " · empty"}</span> : <span className="mr-auto" />}
        <RegionButton disabled={busy} label="Invert" onClick={() => void operation("invert")} />
        <RegionButton disabled={busy} label="Color select" onClick={() => { dispatch(commandIds.toolEnterInpaintRegionEdit, { targetLayerId, regionId: region.id }); dispatch(commandIds.toolSetActive, { tool: "magicWand" }); }} />
        <RegionButton disabled={busy} label="AI object" onClick={() => { dispatch(commandIds.toolEnterInpaintRegionEdit, { targetLayerId, regionId: region.id }); dispatch(commandIds.toolSetActive, { tool: "semanticSelect" }); }} />
        <RegionButton disabled={busy} label="Lasso" onClick={() => { dispatch(commandIds.toolEnterInpaintRegionEdit, { targetLayerId, regionId: region.id }); dispatch(commandIds.toolSetActive, { tool: "maskLasso" }); }} />
        <RegionButton disabled={busy} label="Rectangle" onClick={() => { dispatch(commandIds.toolEnterInpaintRegionEdit, { targetLayerId, regionId: region.id }); dispatch(commandIds.toolSetActive, { tool: "maskRectangle" }); }} />
        <RegionButton disabled={busy} label="Clear" onClick={() => void operation("clear")} />
        <RegionButton disabled={busy} label="Select all" onClick={() => void operation("fill")} />
        <RegionButton disabled={busy} label="Remove" danger onClick={() => dispatch(commandIds.documentRemoveInpaintRegion, { regionId: region.id })} />
      </div>
    </div>
  );
}

function MaskPreview({ label, source }: { label: string; source: string }) {
  return <div className="grid gap-1"><img src={source} alt={`${label} mask preview`} className="h-14 w-full rounded-md bg-black/30 object-cover ring-1 ring-white/10" /><span>{label}</span></div>;
}

function RegionButton({ label, disabled, danger, onClick }: { label: string; disabled?: boolean; danger?: boolean; onClick: () => void }) {
  return <button type="button" disabled={disabled} className={`rounded-md px-2 py-1 font-semibold transition disabled:opacity-35 ${danger ? "bg-red-400/10 text-red-100/70 hover:bg-red-400/20" : "bg-white/[0.05] text-white/55 hover:bg-white/[0.09] hover:text-white"}`} onClick={onClick}>{label}</button>;
}
