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

import (
	"github.com/jordic/goics"
	"htwkalender/ical/model"
	mockTime "htwkalender/ical/service/functions/time"
	"reflect"
	"testing"
	"time"
)

func TestIcalModel_EmitICal(t *testing.T) {
	type fields struct {
		Events  model.Events
		Mapping map[string]model.FeedCollection
	}
	tests := []struct {
		name   string
		fields fields
		want   *goics.Component
	}{
		{
			name: "Test EmitICal",
			fields: fields{
				Events: model.Events{
					{
						UUID:      "123",
						Name:      "Test",
						EventType: "Test",
						Notes:     "Test",
						Prof:      "Test",
						Rooms:     "Test",
						BookedAt:  "Test",
					},
				},
				Mapping: map[string]model.FeedCollection{
					"123": {
						UUID:            "123",
						Name:            "Test",
						Course:          "Test",
						UserDefinedName: "Test",
					},
				},
			},
			want: &goics.Component{
				Tipo: "VCALENDAR",
				Elements: []goics.Componenter{
					&goics.Component{
						Tipo: "VTIMEZONE",
						Elements: []goics.Componenter{
							&HtwkalenderComponent{
								Component: &goics.Component{
									Tipo:     "STANDARD",
									Elements: []goics.Componenter{},
									Properties: map[string][]string{
										"DTSTART":      {"19701025T030000"},
										"RRULE":        {"FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU"},
										"TZOFFSETFROM": {"+0200"},
										"TZOFFSETTO":   {"+0100"},
										"TZNAME":       {"CET"},
									},
								},
							},
							&HtwkalenderComponent{
								Component: &goics.Component{
									Tipo:     "DAYLIGHT",
									Elements: []goics.Componenter{},
									Properties: map[string][]string{
										"DTSTART":      {"19700329T020000"},
										"TZOFFSETFROM": {"+0100"},
										"TZOFFSETTO":   {"+0200"},
										"TZNAME":       {"CEST"},
										"RRULE":        {"FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"},
									},
								},
							},
						},
						Properties: map[string][]string{
							"TZID": {"EUROPE/BERLIN"},
						},
					},
					&goics.Component{
						Tipo:     "VEVENT",
						Elements: []goics.Componenter{},
						Properties: map[string][]string{
							"DTSTAMP":     {"20231201T000000Z"},
							"UID":         {"5166fc0abd9d7750077261f1e26a26168d32c88af77198fe83af63e1ba6310dc@htwkalender.de"},
							"DTEND":       {"00010101T000000Z"},
							"DTSTART":     {"00010101T000000Z"},
							"SUMMARY":     {"Test"},
							"DESCRIPTION": {"Profs: Test\nTyp: Test\nNotizen: Test\n"},
							"LOCATION":    {"Test"},
						},
					},
				},
				Properties: map[string][]string{
					"PRODID":        {"-//HTWK Kalender//htwkalender.de//DE"},
					"VERSION":       {"2.0"},
					"CALSCALE":      {"GREGORIAN"},
					"TZID":          {"EUROPE/BERLIN"},
					"X-WR-CALNAME":  {"HTWK Kalender"},
					"X-WR-TIMEZONE": {"EUROPE/BERLIN"},
				},
			},
		},
		{
			name: "Test Similar Events like Sport Courses",
			fields: fields{
				Events: model.Events{
					{
						UUID:      "123",
						Name:      "Test",
						Course:    "Test",
						EventType: "Test",
						Notes:     "Test",
						Prof:      "Test",
						Rooms:     "ZU430",
						BookedAt:  "Test",
						Start:     mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 0, 0, 0, 0, time.UTC)),
						End:       mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 1, 0, 0, 0, time.UTC)),
					},
					{
						UUID:      "123",
						Name:      "Test",
						Course:    "Test",
						EventType: "Test",
						Notes:     "Test",
						Prof:      "Test",
						Rooms:     "ZU221",
						BookedAt:  "Test",
						Start:     mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 0, 0, 0, 0, time.UTC)),
						End:       mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 1, 0, 0, 0, time.UTC)),
					},
				},
				Mapping: map[string]model.FeedCollection{
					"123": {
						UUID:            "123",
						Name:            "Test",
						Course:          "Test",
						UserDefinedName: "UserDefinedName",
					},
				},
			},
			want: &goics.Component{
				Tipo: "VCALENDAR",
				Elements: []goics.Componenter{
					&goics.Component{
						Tipo: "VTIMEZONE",
						Elements: []goics.Componenter{
							&HtwkalenderComponent{
								Component: &goics.Component{
									Tipo:     "STANDARD",
									Elements: []goics.Componenter{},
									Properties: map[string][]string{
										"DTSTART":      {"19701025T030000"},
										"RRULE":        {"FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU"},
										"TZOFFSETFROM": {"+0200"},
										"TZOFFSETTO":   {"+0100"},
										"TZNAME":       {"CET"},
									},
								},
							},
							&HtwkalenderComponent{
								Component: &goics.Component{
									Tipo:     "DAYLIGHT",
									Elements: []goics.Componenter{},
									Properties: map[string][]string{
										"DTSTART":      {"19700329T020000"},
										"TZOFFSETFROM": {"+0100"},
										"TZOFFSETTO":   {"+0200"},
										"TZNAME":       {"CEST"},
										"RRULE":        {"FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"},
									},
								},
							},
						},
						Properties: map[string][]string{
							"TZID": {"EUROPE/BERLIN"},
						},
					},
					&goics.Component{
						Tipo:     "VEVENT",
						Elements: []goics.Componenter{},
						Properties: map[string][]string{
							"DTSTAMP":     {"20231201T000000Z"},
							"UID":         {"2463aac347bca19130d8e579b4b6d89a32c88f7c7e7f858e56477d94b71543a7@htwkalender.de"},
							"DTEND":       {"20231201T010000Z"},
							"DTSTART":     {"20231201T000000Z"},
							"SUMMARY":     {"UserDefinedName"},
							"DESCRIPTION": {"Profs: Test\nGruppen: Test\nTyp: Test\nNotizen: Test\n"},
							"LOCATION":    {"ZU430"},
						},
					},
					&goics.Component{
						Tipo:     "VEVENT",
						Elements: []goics.Componenter{},
						Properties: map[string][]string{
							"DTSTAMP":     {"20231201T000000Z"},
							"UID":         {"ea42fc31835128735636b235be552af559fae5329fe7e501f529130e11a7f3a1@htwkalender.de"},
							"DTEND":       {"20231201T010000Z"},
							"DTSTART":     {"20231201T000000Z"},
							"SUMMARY":     {"UserDefinedName"},
							"DESCRIPTION": {"Profs: Test\nGruppen: Test\nTyp: Test\nNotizen: Test\n"},
							"LOCATION":    {"ZU221"},
						},
					},
				},
				Properties: map[string][]string{
					"PRODID":        {"-//HTWK Kalender//htwkalender.de//DE"},
					"VERSION":       {"2.0"},
					"CALSCALE":      {"GREGORIAN"},
					"TZID":          {"EUROPE/BERLIN"},
					"X-WR-CALNAME":  {"HTWK Kalender"},
					"X-WR-TIMEZONE": {"EUROPE/BERLIN"},
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			icalModel := IcalModel{
				Events:  tt.fields.Events,
				Mapping: tt.fields.Mapping,
			}

			mockClock := mockTime.MockClock{
				NowTime: time.Date(2023, 12, 1, 0, 0, 0, 0, time.UTC),
			}

			if got := generateIcalEmit(icalModel, mockClock); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("EmitICal() = \n%v, want \n%v", got, tt.want)

				// Print the differences
				for i, element := range got.Elements {
					if !reflect.DeepEqual(element, tt.want.Elements[i]) {
						t.Errorf("Element %d: got \n%v, want \n%v", i, element, tt.want.Elements[i])
					}
				}
			}
		})
	}
}
