package service

import (
	"bytes"
	"image"
	"image/color"
	"image/jpeg"
	"image/png"
	"math/rand"
	"time"

	_ "image/gif"

	_ "golang.org/x/image/webp"
)

// applyDeAI post-processes a generated image to weaken AI-detection artifacts:
// a small edge crop (kills border fingerprints), per-pixel low-amplitude noise,
// a subtle brightness/contrast jitter, and a JPEG re-encode round-trip that
// both introduces natural compression statistics and strips any embedded
// metadata/watermark chunks. Output is PNG (matching the stored content type).
func applyDeAI(b []byte) ([]byte, error) {
	src, _, err := image.Decode(bytes.NewReader(b))
	if err != nil {
		return nil, err
	}
	bounds := src.Bounds()
	w, h := bounds.Dx(), bounds.Dy()

	// Crop a sliver off each edge (~0.3% of the dimension, 2–12px).
	cropX := clampInt(w*3/1000, 2, 12)
	cropY := clampInt(h*3/1000, 2, 12)
	if w <= cropX*4 || h <= cropY*4 {
		cropX, cropY = 0, 0
	}
	x0, y0 := bounds.Min.X+cropX, bounds.Min.Y+cropY
	x1, y1 := bounds.Max.X-cropX, bounds.Max.Y-cropY

	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
	// Subtle tone jitter: contrast ±2%, brightness ±2 levels.
	contrast := 1.0 + (rng.Float64()-0.5)*0.04
	brightness := (rng.Float64() - 0.5) * 4.0

	out := image.NewRGBA(image.Rect(0, 0, x1-x0, y1-y0))
	for y := y0; y < y1; y++ {
		for x := x0; x < x1; x++ {
			r, g, bl, a := src.At(x, y).RGBA()
			out.SetRGBA(x-x0, y-y0, color.RGBA{
				R: jitterChannel(r, contrast, brightness, rng),
				G: jitterChannel(g, contrast, brightness, rng),
				B: jitterChannel(bl, contrast, brightness, rng),
				A: uint8(a >> 8),
			})
		}
	}

	// JPEG round-trip: natural compression statistics + strips metadata.
	var jbuf bytes.Buffer
	if err := jpeg.Encode(&jbuf, out, &jpeg.Options{Quality: 93}); err != nil {
		return nil, err
	}
	rt, err := jpeg.Decode(bytes.NewReader(jbuf.Bytes()))
	if err != nil {
		return nil, err
	}
	var pbuf bytes.Buffer
	if err := png.Encode(&pbuf, rt); err != nil {
		return nil, err
	}
	return pbuf.Bytes(), nil
}

// jitterChannel applies contrast/brightness around mid-gray plus ±2 noise to a
// 16-bit color channel, returning the clamped 8-bit value.
func jitterChannel(v uint32, contrast, brightness float64, rng *rand.Rand) uint8 {
	f := float64(v>>8)
	f = (f-128.0)*contrast + 128.0 + brightness + (rng.Float64()-0.5)*4.0
	if f < 0 {
		f = 0
	}
	if f > 255 {
		f = 255
	}
	return uint8(f + 0.5)
}

func clampInt(n, lo, hi int) int {
	if n < lo {
		return lo
	}
	if n > hi {
		return hi
	}
	return n
}
