//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
//Copyright (C) 2024 HTWKalender support@htwkalender.de

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU Affero General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU Affero General Public License for more details.

//You should have received a copy of the GNU Affero General Public License
//along with this program.  If not, see <https://www.gnu.org/licenses/>.

package room

import (
	"github.com/pocketbase/pocketbase/tools/types"
	"htwkalender/data-manager/model"
	"reflect"
	"testing"
)

func TestAnonymizeRooms(t *testing.T) {
	type args struct {
		events []model.Event
	}
	tests := []struct {
		name string
		args args
		want []model.AnonymizedEventDTO
	}{
		{
			name: "anonymize single event",
			args: args{
				events: []model.Event{
					{
						UUID:       "testUUID",
						Day:        "Montag",
						Week:       "52",
						Start:      types.DateTime{},
						End:        types.DateTime{},
						Name:       "Secret",
						EventType:  "V",
						Prof:       "Prof. Dr. Secret",
						Rooms:      "Room",
						Notes:      "Secret",
						BookedAt:   "Secret",
						Course:     "42INM-3",
						Semester:   "ws",
						Compulsory: "p",
					},
				},
			},
			want: []model.AnonymizedEventDTO{
				{
					Day:       "Montag",
					Week:      "52",
					Start:     types.DateTime{},
					End:       types.DateTime{},
					Rooms:     "Room",
					Name:      "Secret",
					EventType: "V",
					Free:      false,
				},
			},
		},
		{
			name: "anonymize empty list",
			args: args{
				events: []model.Event{},
			},
			want: nil,
		},
		{
			name: "anonymize multiple events",
			args: args{
				events: []model.Event{
					{
						UUID:       "testUUID1",
						Day:        "Montag",
						Week:       "51",
						Start:      types.DateTime{},
						End:        types.DateTime{},
						Name:       "Incognito",
						EventType:  "V",
						Prof:       "Prof. Dr. Incognito",
						Rooms:      "Room",
						Notes:      "Incognito",
						BookedAt:   "Incognito",
						Course:     "69INM-2",
						Semester:   "sose",
						Compulsory: "p",
					},
					{
						UUID:       "testUUID2",
						Day:        "Dienstag",
						Week:       "52",
						Start:      types.DateTime{},
						End:        types.DateTime{},
						Name:       "Private",
						EventType:  "S",
						Prof:       "Prof.In. Dr.-Ing. Private",
						Rooms:      "Room",
						Notes:      "Private",
						BookedAt:   "Private",
						Course:     "42MIM-3",
						Semester:   "ws",
						Compulsory: "w",
					},
				},
			},
			want: []model.AnonymizedEventDTO{
				{
					Day:       "Montag",
					Week:      "51",
					Start:     types.DateTime{},
					End:       types.DateTime{},
					Rooms:     "Room",
					Name:      "Incognito",
					EventType: "V",
					Free:      false,
				},
				{
					Day:       "Dienstag",
					Week:      "52",
					Start:     types.DateTime{},
					End:       types.DateTime{},
					Rooms:     "Room",
					Name:      "Private",
					EventType: "S",
					Free:      false,
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := anonymizeRooms(tt.args.events); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("anonymizeRooms() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestIsRoomInSchedule(t *testing.T) {
	type args struct {
		room     string
		schedule []model.Event
	}
	tests := []struct {
		name string
		args args
		want bool
	}{
		{
			name: "room is in schedule",
			args: args{
				room: "Room",
				schedule: []model.Event{
					{
						UUID:      "testUUID",
						Day:       "Montag",
						Week:      "52",
						Start:     types.DateTime{},
						End:       types.DateTime{},
						Name:      "Secret",
						EventType: "V",
						Prof:      "Prof. Dr. Secret",
						Rooms:     "Room",
						Notes:     "Secret",
					},
				},
			},
			want: true,
		},
		{
			name: "room is not in schedule",
			args: args{
				room: "Z324",
				schedule: []model.Event{
					{
						UUID:      "testUUID",
						Day:       "Montag",
						Week:      "52",
						Start:     types.DateTime{},
						End:       types.DateTime{},
						Name:      "Secret",
						EventType: "V",
						Prof:      "Prof. Dr. Bond",
						Rooms:     "LI007",
						Notes:     "Keine Zeit für die Uni",
					},
				},
			},
			want: false,
		},
		{
			name: "schedule event.Course is sport",
			args: args{
				room: "Klettergerüst",
				schedule: []model.Event{
					{
						UUID:      "903784265784639527",
						Day:       "Montag",
						Week:      "52",
						Start:     types.DateTime{},
						End:       types.DateTime{},
						Name:      "Hampelmann",
						EventType: "S",
						Prof:      "Prof. Dr. Bewegung",
						Rooms:     "Klettergerüst",
						Notes:     "A apple a day keeps the doctor away",
						Course:    "Sport",
					},
				},
			},
			want: true,
		},
		{
			name: "schedule event.Course is sport with different room",
			args: args{
				room: "HTWK Sportplatz",
				schedule: []model.Event{
					{
						UUID:      "903784265784639527",
						Day:       "Montag",
						Week:      "52",
						Start:     types.DateTime{},
						End:       types.DateTime{},
						Name:      "Hampelmann",
						EventType: "S",
						Prof:      "Prof. Dr. Bewegung",
						Rooms:     "Klettergerüst",
						Notes:     "A apple a day keeps the doctor away",
						Course:    "Sport",
					},
				},
			},
			want: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := isRoomInSchedule(tt.args.room, tt.args.schedule); got != tt.want {
				t.Errorf("isRoomInSchedule() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestGetFreeRooms(t *testing.T) {
	type args struct {
		rooms    []string
		schedule []model.Event
	}
	tests := []struct {
		name string
		args args
		want []string
	}{
		{
			name: "remove room1 from list",
			args: args{
				rooms: []string{
					"Room1",
					"Room2",
					"Room3",
				},
				schedule: []model.Event{
					{
						UUID:      "testUUID",
						Day:       "Montag",
						Week:      "52",
						Start:     types.DateTime{},
						End:       types.DateTime{},
						Name:      "Secret",
						EventType: "V",
						Prof:      "Prof. Dr. Secret",
						Rooms:     "Room1",
						Notes:     "Secret",
					},
				},
			},
			want: []string{
				"Room2",
				"Room3",
			},
		},
		{
			name: "remove room2 from list",
			args: args{
				rooms: []string{
					"Room1",
					"Room2",
					"Room3",
				},
				schedule: []model.Event{
					{
						UUID:      "testUUID",
						Day:       "Montag",
						Week:      "52",
						Start:     types.DateTime{},
						End:       types.DateTime{},
						Name:      "Secret",
						EventType: "V",
						Prof:      "Prof. Dr. Secret",
						Rooms:     "Room3",
						Notes:     "Secret",
					},
				},
			},
			want: []string{
				"Room1",
				"Room2",
			},
		},
		{
			name: "remove no room from list",
			args: args{
				rooms: []string{
					"Room1",
					"Room2",
					"Room3",
				},
				schedule: []model.Event{
					{
						UUID:      "testUUID",
						Day:       "Montag",
						Week:      "52",
						Start:     types.DateTime{},
						End:       types.DateTime{},
						Name:      "Secret",
						EventType: "V",
						Prof:      "Prof. Dr. Secret",
						Rooms:     "Room4",
						Notes:     "Secret",
					},
				},
			},
			want: []string{
				"Room1",
				"Room2",
				"Room3",
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := removeRoomsThatHaveEvents(tt.args.rooms, tt.args.schedule); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("removeRoomsThatHaveEvents() = %v, want %v", got, tt.want)
			}
		})
	}
}
