#include "png_diff.h"

#include "stb_image.h"

#include <cstdlib>

namespace fn_test {

PngDiffResult pixel_diff_ratio(const std::string& path_a,
                               const std::string& path_b,
                               int channel_threshold) {
    PngDiffResult r;
    int wa = 0, ha = 0, ca = 0;
    int wb = 0, hb = 0, cb = 0;
    unsigned char* a = stbi_load(path_a.c_str(), &wa, &ha, &ca, 4);
    unsigned char* b = stbi_load(path_b.c_str(), &wb, &hb, &cb, 4);
    r.loaded_a = (a != nullptr);
    r.loaded_b = (b != nullptr);
    r.width_a = wa; r.height_a = ha;
    r.width_b = wb; r.height_b = hb;

    if (!r.loaded_a || !r.loaded_b) {
        if (a) stbi_image_free(a);
        if (b) stbi_image_free(b);
        return r;
    }

    if (wa != wb || ha != hb) {
        // Dimensiones no coinciden — diff total.
        const long area_a = (long)wa * ha;
        const long area_b = (long)wb * hb;
        r.pixels_total     = area_a > area_b ? area_a : area_b;
        r.pixels_different = r.pixels_total;
        r.diff_ratio       = 1.0;
        stbi_image_free(a);
        stbi_image_free(b);
        return r;
    }

    const long area = (long)wa * ha;
    long diffs = 0;
    for (long i = 0; i < area; ++i) {
        const unsigned char* pa = a + i * 4;
        const unsigned char* pb = b + i * 4;
        const int dr = std::abs((int)pa[0] - (int)pb[0]);
        const int dg = std::abs((int)pa[1] - (int)pb[1]);
        const int db_ = std::abs((int)pa[2] - (int)pb[2]);
        const int da = std::abs((int)pa[3] - (int)pb[3]);
        if (dr > channel_threshold || dg > channel_threshold ||
            db_ > channel_threshold || da > channel_threshold) {
            ++diffs;
        }
    }

    r.pixels_total     = area;
    r.pixels_different = diffs;
    r.diff_ratio       = (area > 0) ? (double)diffs / (double)area : 0.0;

    stbi_image_free(a);
    stbi_image_free(b);
    return r;
}

} // namespace fn_test
