#include <string.h>

#include "administration.h"
#include "unity.h"
#include "unity_test_module.h"

// I rather dislike keeping line numbers updated, so I made my own macro to ditch the line number
#define MY_RUN_TEST(func) RUN_TEST(func, 0)

// Keep the original array constant to prevent modifications
const Animal originalArray[5] = {
    {.Id = 1, .Species = Cat, .Age = 8, .Sex = Male, .DateFound = {1, 1, 2020}},
    {.Id = 2, .Species = Dog, .Age = 2, .Sex = Female, .DateFound = {1, 1, 2021}},
    {.Id = 3, .Species = GuineaPig, .Age = 92, .Sex = Female, .DateFound = {1, 1, 2022}}
};

// Arrays for testing
Animal animalArray[5];
Animal searchArray[5];

void administration_setUp(void) {
    // Reset both arrays before each test
    memcpy(animalArray, originalArray, sizeof(originalArray));
    memcpy(searchArray, originalArray, sizeof(originalArray));
}

void administration_tearDown(void){}

void test_administration_remove_valid(void){
    size_t newNumberOfAnimalsPresent = 0;
    int errorCode = removeAnimal(2, animalArray, 3, &newNumberOfAnimalsPresent);
    TEST_ASSERT_EQUAL(0, errorCode);
    TEST_ASSERT_EQUAL(2, newNumberOfAnimalsPresent);
}

void test_administration_remove_invalid(void){
    size_t newNumberOfAnimalsPresent = 0;
    int errorCode = removeAnimal(12, animalArray, 3, &newNumberOfAnimalsPresent);
    TEST_ASSERT_EQUAL(-1, errorCode);
    TEST_ASSERT_EQUAL(3, newNumberOfAnimalsPresent);
}

void test_administration_add_valid(void){
    Animal newAnimal = {.Id = 4, .Species = Dog, .Age = 3, .Sex = Male, .DateFound = {1, 1, 2023}};
    size_t newNumberOfAnimalsPresent = 0;
    int errorCode = addAnimal(&newAnimal, animalArray, 5, 3, &newNumberOfAnimalsPresent);
    TEST_ASSERT_EQUAL(0, errorCode);
    TEST_ASSERT_EQUAL(4, newNumberOfAnimalsPresent);
}

void test_administration_add_invalid(void){
    Animal newAnimal = {.Id = 5, .Species = Cat, .Age = 2, .Sex = Female, .DateFound = {1, 1, 2024}};
    size_t newNumberOfAnimalsPresent = 0;
    int errorCode = addAnimal(&newAnimal, animalArray, 3, 3, &newNumberOfAnimalsPresent);
    TEST_ASSERT_EQUAL(-1, errorCode);
    TEST_ASSERT_EQUAL(3, newNumberOfAnimalsPresent);
}

void test_administration_find_valid(void){
    Animal foundAnimalV;
    int errorCode = findAnimalById(2, searchArray, 3, &foundAnimalV);
    TEST_ASSERT_EQUAL(0, errorCode);
    TEST_ASSERT_EQUAL(2, foundAnimalV.Id);
    TEST_ASSERT_EQUAL(Dog, foundAnimalV.Species);
}

void test_administration_find_invalid(void){
    Animal foundAnimalinV;
    int errorCode = findAnimalById(12, searchArray, 3, &foundAnimalinV);
    TEST_ASSERT_EQUAL(-1, errorCode);
    TEST_ASSERT_EQUAL(0, foundAnimalinV.Id);
}

void run_administration_tests()
{
    UnityRegisterSetupTearDown(administration_setUp, administration_tearDown);

    MY_RUN_TEST(test_administration_remove_valid);
    MY_RUN_TEST(test_administration_remove_invalid);
    MY_RUN_TEST(test_administration_add_valid);
    MY_RUN_TEST(test_administration_add_invalid);
    MY_RUN_TEST(test_administration_find_valid);
    MY_RUN_TEST(test_administration_find_invalid);

    UnityUnregisterSetupTearDown();
}
