#ifdef TEST
#include "unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "Spieler.h"
#include "Koenig.h"
#include "Schachbrett.h"

char** ErstelleTestBrett() {
    char** Brett = malloc(8 * sizeof(char*));
    for (int i = 0; i < 8; i++) {
        Brett[i] = malloc(8 * sizeof(char));
        for (int j = 0; j < 8; j++) {
            Brett[i][j] = ' '; //Erstelle komplett leeres Brett
        }
    }
    return Brett;
}

void freeTestBrett(char** Brett) {
    for (int i = 0; i < 8; i++) {
        free(Brett[i]);
    }
    free(Brett);
}

void test_GreiftBauerAn(void) {
    char** Brett = ErstelleTestBrett();

    // Plaziert weißen Bauer auf d5 (3,4) und testet 'angriff' auf c6 (2,5) und e6 (4,5)
    Brett[4][3] = 'P';
    Player player = PLAYER_BLACK;
    TEST_ASSERT_TRUE(GreiftBauerAn(Brett, 2, 5, player));
    TEST_ASSERT_TRUE(GreiftBauerAn(Brett, 4, 5, player));

    // Plaziert schwarzen Bauer auf e4 (4,3) und testet 'angriff' auf d3 (3,2) und f3 (5,2)
    Brett[3][4] = 'p';
    player = PLAYER_WHITE;
    TEST_ASSERT_TRUE(GreiftBauerAn(Brett, 3, 2, player));
    TEST_ASSERT_TRUE(GreiftBauerAn(Brett, 5, 2, player));

    // Test ein Feld ohne Bedrohung
    TEST_ASSERT_FALSE(GreiftBauerAn(Brett, 0, 0, player));

    freeTestBrett(Brett);
}

void test_GreiftTurmAn(void) {
    char** Brett = ErstelleTestBrett(); 

    // Plaziert weißen Turm auf d4 (3,3) und testet für Angriffe
    Brett[3][3] = 'R';
    Player player = PLAYER_BLACK;
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 3, 0, player)); // Checkt vertikalen Angriff auf d1
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 3, 7, player)); // Checkt vertikalen Angriff auf d8
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 0, 3, player)); // Checkt horizontalen Angriff auf a4
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 7, 3, player)); // Checkt horizontalen Angriff auf h4

    // Plaziert schwarzen Turm auf e5 (4,4) und Tauscht Spieler zu weiß
    Brett[3][3] = ' '; // Alten turm wegmachen
    Brett[4][4] = 'r';
    player = PLAYER_WHITE;
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 4, 0, player)); // Checkt vertikalen Angriff auf e1
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 4, 7, player)); // Checkt vertikalen Angriff auf e8
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 0, 4, player)); // Checkt horizontalen Angriff auf a5
    TEST_ASSERT_TRUE(GreiftTurmAn(Brett, 7, 4, player)); // Checkt horizontalen Angriff auf h5

    // Checkt sicheres Feld
    TEST_ASSERT_FALSE(GreiftTurmAn(Brett, 0, 0, player));

    freeTestBrett(Brett);
}

void test_GreiftSpringerAn(void) {
    char** Brett = ErstelleTestBrett();

    // Plaziert ein schwarzen Springer (3,4) und testet 'Angriff' auf e3 (4,2)
    Brett[4][3] = 'n';
    Player player = PLAYER_WHITE;
    TEST_ASSERT_TRUE(GreiftSpringerAn(Brett, 4, 2, player));

    // Plaziert ein weißen Springer (5,2) und testet 'Angriff' auf e5 (4,4)
    Brett[2][5] = 'N';
    player = PLAYER_BLACK;
    TEST_ASSERT_TRUE(GreiftSpringerAn(Brett, 4, 4, player));

    // Testet Feld ohne Bedrohung
    TEST_ASSERT_FALSE(GreiftSpringerAn(Brett, 0, 0, player));

    freeTestBrett(Brett);
}
void test_GreiftLaeuferAn(void) {
    char** Brett = ErstelleTestBrett(); 

    // Plaziert einen weißen Läufer auf c4 (2,3) und testet Angriffe
    Brett[3][2] = 'B';

    Player player = PLAYER_BLACK;
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 0, 1, player)); // Check unten Links
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 5, 0, player)); // Check oben Links
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 4, 5, player)); // Check unten Rechts
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 3, 2, player)); // Check oben Rechts

    // Plaziert einen schwarzen Läufer auf e5 (4,4) und testet Angriffe vom anderen spieler
    Brett[2][3] = ' ';
    Brett[4][4] = 'b';
    player = PLAYER_WHITE;
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 2, 2, player)); // Check unten Rechts
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 2, 6, player)); // Check oben Links
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 6, 6, player)); // Check unten Rechts
    TEST_ASSERT_TRUE(GreiftLaeuferAn(Brett, 6, 2, player)); // Check oben Rechts

    // Check sicheres Feld
    TEST_ASSERT_FALSE(GreiftLaeuferAn(Brett, 0, 1, player));

    freeTestBrett(Brett); 
}
void test_GreiftDameAn(void) {
    char** Brett = ErstelleTestBrett();

    // Plaziert weiße dame auf d4
    Brett[3][3] = 'Q';
    Player player = PLAYER_BLACK;

    // Test Oben/Seitlich
    TEST_ASSERT_TRUE(GreiftDameAn(Brett, 3, 7, player)); // d8
    TEST_ASSERT_TRUE(GreiftDameAn(Brett, 0, 3, player)); // a4

    // Test Diagonal
    TEST_ASSERT_TRUE(GreiftDameAn(Brett, 1, 5, player)); // b6

    // Plaziert eigene Figur zum blocken
    Brett[4][3] = 'P';
    // Test blockiert von eigener Figur
    TEST_ASSERT_FALSE(GreiftDameAn(Brett, 3, 7, player)); // d8 blocked

    freeTestBrett(Brett);
}
void test_GreiftKoenigAn(void) {
    char** Brett = ErstelleTestBrett();

    // Plaziert schwarzen König auf e5 (4,4) und einen weißen auf d4 (3,3)
    Brett[4][4] = 'k';
    Brett[3][3] = 'K';
    print_Schachfeld(Brett);
    // Test ob der schwarze könig Felder angreifen kann
    TEST_ASSERT_TRUE(GreiftKoenigAn(Brett, 3, 4, PLAYER_WHITE)); // d5
    TEST_ASSERT_TRUE(GreiftKoenigAn(Brett, 5, 4, PLAYER_WHITE)); // f5
    TEST_ASSERT_TRUE(GreiftKoenigAn(Brett, 4, 3, PLAYER_WHITE)); // e4

    // Test ob der weiße könig Felder angreifen kann
    TEST_ASSERT_TRUE(GreiftKoenigAn(Brett, 2, 3, PLAYER_BLACK)); // c4
    TEST_ASSERT_TRUE(GreiftKoenigAn(Brett, 3, 2, PLAYER_BLACK)); // d3
    TEST_ASSERT_TRUE(GreiftKoenigAn(Brett, 4, 3, PLAYER_BLACK)); // e4

    // Tests für nicht angegriffene Felder
    TEST_ASSERT_FALSE(GreiftKoenigAn(Brett, 2, 4, PLAYER_WHITE));
    TEST_ASSERT_FALSE(GreiftKoenigAn(Brett, 6, 4, PLAYER_WHITE));
    TEST_ASSERT_FALSE(GreiftKoenigAn(Brett, 1, 3, PLAYER_BLACK));
    TEST_ASSERT_FALSE(GreiftKoenigAn(Brett, 5, 3, PLAYER_BLACK));
    TEST_ASSERT_FALSE(GreiftKoenigAn(Brett, 3, 1, PLAYER_BLACK));

    freeTestBrett(Brett);
}
void test_istFeldUnsicher(void) {
    char** Brett = ErstelleTestBrett();
    Brett[4][4] = 'p';
    Player player = PLAYER_WHITE;
    print_Schachfeld(Brett);
    TEST_ASSERT_TRUE(istFeldUnsicher(Brett, 5, 3, player));
    TEST_ASSERT_FALSE(istFeldUnsicher(Brett, 0, 0, player));

    Brett[4][4] = ' ';
    Brett[0][1] = 'N';
    player = PLAYER_BLACK;

    TEST_ASSERT_TRUE(istFeldUnsicher(Brett, 2, 2, player));
    TEST_ASSERT_FALSE(istFeldUnsicher(Brett, 0, 0, player));

    Brett[0][1] = ' ';
    Brett[7][0] = 'r';
    player = PLAYER_WHITE;

    TEST_ASSERT_TRUE(istFeldUnsicher(Brett, 0, 0, player));
    TEST_ASSERT_FALSE(istFeldUnsicher(Brett, 4, 4, player));

    Brett[7][0] = ' ';
    Brett[3][3] = 'Q';
    player = PLAYER_BLACK;
    TEST_ASSERT_TRUE(istFeldUnsicher(Brett, 7, 7, player));
    TEST_ASSERT_TRUE(istFeldUnsicher(Brett, 3, 0, player));

    freeTestBrett(Brett);
}
#endif // TEST