#include "transcriber.h"
#include "text_util.h"
#include <cstdio>
#include <cstdint>
#include <fstream>
#include <vector>
#include <string>
#include <cctype>

static int g_fail = 0;
#define CHECK(cond, msg) do { if (!(cond)) { printf("  FAIL: %s\n", msg); ++g_fail; } \
                              else            printf("  ok:   %s\n", msg); } while(0)

static bool load_wav(const std::string& path, std::vector<float>& out) {
    std::ifstream f(path, std::ios::binary);
    if (!f) return false;
    char hdr[44];
    f.read(hdr, 44);
    if (std::string(hdr, 4) != "RIFF") return false;
    std::vector<int16_t> pcm((std::istreambuf_iterator<char>(f)), {});
    out.clear(); out.reserve(pcm.size());
    for (int16_t s : pcm) out.push_back(s / 32768.0f);
    return !out.empty();
}

static std::string lower(std::string s) { for (char& c : s) c = (char)tolower((unsigned char)c); return s; }

int main(int argc, char** argv) {
    std::string model = (argc > 1) ? argv[1] : "models/ggml-tiny.en.bin";
    std::string wav   = (argc > 2) ? argv[2] : "samples/jfk.wav";

    CHECK(append_transcript(L"", L"hello") == L"hello",           "append: empty + a");
    CHECK(append_transcript(L"hello", L"world") == L"hello world", "append: a + b spaced");
    CHECK(append_transcript(L"hello", L"") == L"hello",           "append: a + empty");

    {
        Transcriber t; WhisperConfig bad; bad.model_path = "models\\does-not-exist.bin";
        bool ok = t.preload(bad);
        CHECK(!ok, "bad model path: preload returns false");
        std::vector<float> a(16000, 0.0f);
        std::string r = t.transcribe_sync(a);
        CHECK(r.empty(), "bad model path: transcribe_sync returns empty, no crash");
    }

    {
        Transcriber t; WhisperConfig cfg; cfg.model_path = model; cfg.n_threads = 4;
        bool ok = t.preload(cfg);
        CHECK(ok, "model loads");
        if (ok) {
            int last = -1, maxp = 0; bool monotonic = true;
            t.set_progress_callback([&](int p) {
                if (p < last) monotonic = false;
                last = p; if (p > maxp) maxp = p;
            });

            std::vector<float> audio;
            bool loaded = load_wav(wav, audio);
            CHECK(loaded, "wav loads");
            if (loaded) {
                std::string text = lower(t.transcribe_sync(audio));
                CHECK(!text.empty(), "transcription is non-empty");
                CHECK(text.find("country") != std::string::npos, "transcription contains 'country'");
                CHECK(monotonic, "progress is non-decreasing");
                CHECK(maxp >= 95, "progress reaches ~100%");
            }
        }
    }

    {
        Transcriber t; WhisperConfig cfg; cfg.model_path = model;
        if (t.preload(cfg)) {
            std::vector<float> tiny(100, 0.1f);
            std::string r = t.transcribe_sync(tiny);
            CHECK(true, "short audio did not crash");
        }
    }

    printf("\n%s (%d failure%s)\n", g_fail ? "TESTS FAILED" : "ALL TESTS PASSED",
           g_fail, g_fail == 1 ? "" : "s");
    return g_fail ? 1 : 0;
}
