//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 model

import (
	"github.com/pocketbase/pocketbase/models"
	"reflect"
	"testing"
	"time"
)

func TestEvents_Contains(t *testing.T) {
	// parse time for JSONTime "2020-01-01 12:00:00.000Z"
	specificTime, _ := time.Parse("2006-01-02T15:04:05.000Z", "2020-01-01T12:00:00.000Z")
	specificJSONTime := JSONTime(specificTime)

	type args struct {
		event Event
	}
	tests := []struct {
		name string
		m    Events
		args args
		want bool
	}{
		{
			name: "empty events",
			m:    Events{},
			args: args{event: Event{}},
			want: false,
		},
		{
			name: "one event",
			m:    Events{{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}},
			args: args{event: Event{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}},
			want: true,
		},
		{
			name: "two events",
			m:    Events{{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}, {Day: "test2", Week: "test2", Start: specificJSONTime, End: specificJSONTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}},
			args: args{event: Event{Day: "test2", Week: "test2", Start: specificJSONTime, End: specificJSONTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}},
			want: true,
		},
		{
			name: "two events with different values",
			m:    Events{{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test", UUID: "439ßu56rf8u9ijn4f4-2345345"}, {Day: "test2", Week: "test2", Start: specificJSONTime, End: specificJSONTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2", UUID: "432a39ßu545349ijn4f4-23dsa45"}},
			args: args{event: Event{Day: "test3", Week: "test3", Start: specificJSONTime, End: specificJSONTime, Name: "test3", Course: "test3", Prof: "test3", Rooms: "test3", EventType: "test3", UUID: "934mf43r34f-g68h7655tg3"}},
			want: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := tt.m.Contains(tt.args.event); got != tt.want {
				t.Errorf("Contains() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestEvent_Equals(t *testing.T) {

	specificTime, _ := time.Parse("2006-01-02T15:04:05.000Z", "2020-01-01T12:00:00.000Z")
	specificJSONTime := JSONTime(specificTime)

	type fields struct {
		UUID      string
		Day       string
		Week      string
		Start     JSONTime
		End       JSONTime
		Name      string
		EventType string
		Prof      string
		Rooms     string
		Notes     string
		BookedAt  string
		Course    string
		Semester  string
		BaseModel models.BaseModel
	}
	type args struct {
		event Event
	}
	tests := []struct {
		name   string
		fields fields
		args   args
		want   bool
	}{
		{
			name:   "empty events",
			fields: fields{},
			args:   args{event: Event{}},
			want:   true,
		},
		{
			name:   "one empty one not",
			fields: fields{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"},
			args:   args{event: Event{}},
			want:   false,
		},
		{
			name:   "one event",
			fields: fields{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"},
			args:   args{event: Event{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}},
			want:   true,
		},
		{
			name:   "two events",
			fields: fields{Day: "test", Week: "test", Start: specificJSONTime, End: specificJSONTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"},
			args:   args{event: Event{Day: "test2", Week: "test2", Start: specificJSONTime, End: specificJSONTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}},
			want:   false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m := &Event{
				UUID:      tt.fields.UUID,
				Day:       tt.fields.Day,
				Week:      tt.fields.Week,
				Start:     tt.fields.Start,
				End:       tt.fields.End,
				Name:      tt.fields.Name,
				EventType: tt.fields.EventType,
				Prof:      tt.fields.Prof,
				Rooms:     tt.fields.Rooms,
				Notes:     tt.fields.Notes,
				BookedAt:  tt.fields.BookedAt,
				Course:    tt.fields.Course,
				Semester:  tt.fields.Semester,
				BaseModel: tt.fields.BaseModel,
			}
			if got := m.Equals(tt.args.event); got != tt.want {
				t.Errorf("Equals() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestEvent_AnonymizeEvent(t *testing.T) {
	type fields struct {
		UUID       string
		Day        string
		Week       string
		Start      JSONTime
		End        JSONTime
		Name       string
		EventType  string
		Compulsory string
		Prof       string
		Rooms      string
		Notes      string
		BookedAt   string
		Course     string
		Semester   string
		BaseModel  models.BaseModel
	}
	tests := []struct {
		name   string
		fields fields
		want   AnonymizedEventDTO
	}{
		{
			name:   "empty event",
			fields: fields{},
			want:   AnonymizedEventDTO{Day: "", Week: "", Start: JSONTime{}, End: JSONTime{}, Rooms: "", Free: false},
		},
		{
			name:   "one event",
			fields: fields{Name: "Event", Day: "test", Week: "test", Rooms: "test"},
			want:   AnonymizedEventDTO{Day: "test", Week: "test", Start: JSONTime{}, End: JSONTime{}, Rooms: "test", Free: false},
		},
		{
			name:   "one event with free",
			fields: fields{Name: "Räume zur freien Verfügung", Day: "test", Week: "test", Rooms: "test", Course: "test"},
			want:   AnonymizedEventDTO{Day: "test", Week: "test", Start: JSONTime{}, End: JSONTime{}, Rooms: "test", Free: true},
		},
		{
			name:   "another free event",
			fields: fields{Name: "Zur freien Verfügung", Day: "Montag", Week: "5", Start: JSONTime{}, End: JSONTime{}, Rooms: "TR_A1.28-S", Course: "42INM-3"},
			want:   AnonymizedEventDTO{Day: "Montag", Week: "5", Start: JSONTime{}, End: JSONTime{}, Rooms: "TR_A1.28-S", Free: true},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m := &Event{
				UUID:       tt.fields.UUID,
				Day:        tt.fields.Day,
				Week:       tt.fields.Week,
				Start:      tt.fields.Start,
				End:        tt.fields.End,
				Name:       tt.fields.Name,
				EventType:  tt.fields.EventType,
				Compulsory: tt.fields.Compulsory,
				Prof:       tt.fields.Prof,
				Rooms:      tt.fields.Rooms,
				Notes:      tt.fields.Notes,
				BookedAt:   tt.fields.BookedAt,
				Course:     tt.fields.Course,
				Semester:   tt.fields.Semester,
				BaseModel:  tt.fields.BaseModel,
			}
			if got := m.AnonymizeEvent(); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("Event.AnonymizeEvent() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestEvent_GetName(t *testing.T) {
	type fields struct {
		UUID       string
		Day        string
		Week       string
		Start      JSONTime
		End        JSONTime
		Name       string
		EventType  string
		Compulsory string
		Prof       string
		Rooms      string
		Notes      string
		BookedAt   string
		Course     string
		Semester   string
		BaseModel  models.BaseModel
	}
	tests := []struct {
		name   string
		fields fields
		want   string
	}{
		{
			name:   "empty event",
			fields: fields{},
			want:   "",
		},
		{
			name:   "one event",
			fields: fields{Name: "Event"},
			want:   "Event",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			e := &Event{
				UUID:       tt.fields.UUID,
				Day:        tt.fields.Day,
				Week:       tt.fields.Week,
				Start:      tt.fields.Start,
				End:        tt.fields.End,
				Name:       tt.fields.Name,
				EventType:  tt.fields.EventType,
				Compulsory: tt.fields.Compulsory,
				Prof:       tt.fields.Prof,
				Rooms:      tt.fields.Rooms,
				Notes:      tt.fields.Notes,
				BookedAt:   tt.fields.BookedAt,
				Course:     tt.fields.Course,
				Semester:   tt.fields.Semester,
				BaseModel:  tt.fields.BaseModel,
			}
			if got := e.GetName(); got != tt.want {
				t.Errorf("GetName() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestEvent_SetCourse(t *testing.T) {
	type fields struct {
		UUID       string
		Day        string
		Week       string
		Start      JSONTime
		End        JSONTime
		Name       string
		EventType  string
		Compulsory string
		Prof       string
		Rooms      string
		Notes      string
		BookedAt   string
		Course     string
		Semester   string
		BaseModel  models.BaseModel
	}
	type args struct {
		course string
	}
	tests := []struct {
		name   string
		fields fields
		args   args
		want   Event
	}{
		{
			name:   "set course",
			fields: fields{},
			args:   args{course: "test"},
			want:   Event{Course: "test"},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			e := &Event{
				UUID:       tt.fields.UUID,
				Day:        tt.fields.Day,
				Week:       tt.fields.Week,
				Start:      tt.fields.Start,
				End:        tt.fields.End,
				Name:       tt.fields.Name,
				EventType:  tt.fields.EventType,
				Compulsory: tt.fields.Compulsory,
				Prof:       tt.fields.Prof,
				Rooms:      tt.fields.Rooms,
				Notes:      tt.fields.Notes,
				BookedAt:   tt.fields.BookedAt,
				Course:     tt.fields.Course,
				Semester:   tt.fields.Semester,
				BaseModel:  tt.fields.BaseModel,
			}
			if got := e.SetCourse(tt.args.course); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("SetCourse() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestEvent_SetName(t *testing.T) {
	type fields struct {
		UUID       string
		Day        string
		Week       string
		Start      JSONTime
		End        JSONTime
		Name       string
		EventType  string
		Compulsory string
		Prof       string
		Rooms      string
		Notes      string
		BookedAt   string
		Course     string
		Semester   string
		BaseModel  models.BaseModel
	}
	type args struct {
		name string
	}
	tests := []struct {
		name   string
		fields fields
		args   args
	}{
		{
			name: "set name",
			fields: fields{
				Name: "name",
			},
			args: args{
				name: "name",
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			e := &Event{
				UUID:       tt.fields.UUID,
				Day:        tt.fields.Day,
				Week:       tt.fields.Week,
				Start:      tt.fields.Start,
				End:        tt.fields.End,
				Name:       tt.fields.Name,
				EventType:  tt.fields.EventType,
				Compulsory: tt.fields.Compulsory,
				Prof:       tt.fields.Prof,
				Rooms:      tt.fields.Rooms,
				Notes:      tt.fields.Notes,
				BookedAt:   tt.fields.BookedAt,
				Course:     tt.fields.Course,
				Semester:   tt.fields.Semester,
				BaseModel:  tt.fields.BaseModel,
			}
			e.SetName(tt.args.name)
		})
	}
}

func TestEvent_TableName(t *testing.T) {
	type fields struct {
		UUID       string
		Day        string
		Week       string
		Start      JSONTime
		End        JSONTime
		Name       string
		EventType  string
		Compulsory string
		Prof       string
		Rooms      string
		Notes      string
		BookedAt   string
		Course     string
		Semester   string
		BaseModel  models.BaseModel
	}
	tests := []struct {
		name   string
		fields fields
		want   string
	}{
		{
			name:   "table name",
			fields: fields{},
			want:   "events",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			e := &Event{
				UUID:       tt.fields.UUID,
				Day:        tt.fields.Day,
				Week:       tt.fields.Week,
				Start:      tt.fields.Start,
				End:        tt.fields.End,
				Name:       tt.fields.Name,
				EventType:  tt.fields.EventType,
				Compulsory: tt.fields.Compulsory,
				Prof:       tt.fields.Prof,
				Rooms:      tt.fields.Rooms,
				Notes:      tt.fields.Notes,
				BookedAt:   tt.fields.BookedAt,
				Course:     tt.fields.Course,
				Semester:   tt.fields.Semester,
				BaseModel:  tt.fields.BaseModel,
			}
			if got := e.TableName(); got != tt.want {
				t.Errorf("TableName() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestEvents_Contains1(t *testing.T) {
	type args struct {
		event Event
	}
	tests := []struct {
		name string
		m    Events
		args args
		want bool
	}{
		{
			name: "empty events",
			m:    Events{},
			args: args{event: Event{}},
			want: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := tt.m.Contains(tt.args.event); got != tt.want {
				t.Errorf("Contains() = %v, want %v", got, tt.want)
			}
		})
	}
}
