package app

import (
	"evening_detective_server/internal/modules/formatter_utils"
	"evening_detective_server/internal/modules/storytelling"
	"evening_detective_server/internal/services/scenarios_service"
	proto "evening_detective_server/proto"

	"google.golang.org/protobuf/types/known/timestamppb"
)

// textFormatter — форматирование текста при конвертации входящих данных.
var textFormatter = formatter_utils.NewFormatter()

func mapScenarios(o []*scenarios_service.Scenario) []*proto.Scenario {
	res := make([]*proto.Scenario, 0, len(o))
	for _, item := range o {
		res = append(res, mapScenario(item))
	}
	return res
}

func mapScenario(o *scenarios_service.Scenario) *proto.Scenario {
	if o == nil {
		return nil
	}
	var publishedAt *timestamppb.Timestamp
	if o.PublishedAt != nil {
		publishedAt = timestamppb.New(*o.PublishedAt)
	}
	return &proto.Scenario{
		Id:          int32(o.ID),
		Name:        o.Name,
		Description: o.Description,
		Image:       o.Image,
		Story:       mapStory(o.Story),
		Author:      mapUser(o.Author),
		Status:      o.Status,
		UpdatedAt:   timestamppb.New(o.UpdatedAt),
		CreatedAt:   timestamppb.New(o.CreatedAt),
		PublishedAt: publishedAt,
	}
}

func mapStory(o *storytelling.Story) *proto.Story {
	if o == nil {
		return nil
	}
	return &proto.Story{
		Introduction: mapIntroduction(o.Introduction),
		Places:       mapPlaces(o.Places),
	}
}

func mapIntroduction(o *storytelling.Introduction) *proto.Introduction {
	if o == nil {
		return nil
	}
	return &proto.Introduction{
		Text:  o.Text,
		Audio: o.Audio,
	}
}

func mapPlaces(o []*storytelling.Place) []*proto.Place {
	res := make([]*proto.Place, 0, len(o))
	for _, item := range o {
		res = append(res, mapPlace(item))
	}
	return res
}

func mapPlace(o *storytelling.Place) *proto.Place {
	return &proto.Place{
		Code:         o.Code,
		Name:         o.Name,
		Text:         o.Text,
		Image:        o.Image,
		Hidden:       o.Hidden,
		Applications: mapApplications(o.Applications),
		Doors:        mapDoors(o.Doors),
		Keys:         mapKeys(o.Keys),
	}
}

func mapApplications(o []*storytelling.Application) []*proto.Application {
	res := make([]*proto.Application, 0, len(o))
	for _, item := range o {
		res = append(res, mapApplication(item))
	}
	return res
}

func mapDoors(o []*storytelling.Door) []*proto.Door {
	res := make([]*proto.Door, 0, len(o))
	for _, item := range o {
		res = append(res, mapDoor(item))
	}
	return res
}

func mapKeys(o []*storytelling.Key) []*proto.Key {
	res := make([]*proto.Key, 0, len(o))
	for _, item := range o {
		res = append(res, mapKey(item))
	}
	return res
}

func mapApplication(o *storytelling.Application) *proto.Application {
	return &proto.Application{
		Name:     o.Name,
		Image:    o.Image,
		FileType: o.FileType,
	}
}

func mapDoor(o *storytelling.Door) *proto.Door {
	return &proto.Door{
		Code: o.Code,
		Name: o.Name,
		Keys: mapKeys(o.Keys),
	}
}

func mapKey(o *storytelling.Key) *proto.Key {
	return &proto.Key{
		Name: o.Name,
	}
}

func convertPlace(o *proto.Place) *storytelling.Place {
	return &storytelling.Place{
		Code:         o.Code,
		Name:         textFormatter.FormatString(o.Name),
		Text:         textFormatter.FormatText(o.Text),
		Image:        o.Image,
		Hidden:       o.Hidden,
		Applications: convertApplications(o.Applications),
		Doors:        convertDoors(o.Doors),
		Keys:         convertKeys(o.Keys),
	}
}

func convertApplications(o []*proto.Application) []*storytelling.Application {
	res := make([]*storytelling.Application, 0, len(o))
	for _, item := range o {
		res = append(res, convertApplication(item))
	}
	return res
}

func convertDoors(o []*proto.Door) []*storytelling.Door {
	res := make([]*storytelling.Door, 0, len(o))
	for _, item := range o {
		res = append(res, convertDoor(item))
	}
	return res
}

func convertKeys(o []*proto.Key) []*storytelling.Key {
	res := make([]*storytelling.Key, 0, len(o))
	for _, item := range o {
		res = append(res, convertKey(item))
	}
	return res
}

func convertApplication(o *proto.Application) *storytelling.Application {
	return &storytelling.Application{
		Name:     textFormatter.FormatString(o.Name),
		Image:    o.Image,
		FileType: o.FileType,
	}
}

func convertDoor(o *proto.Door) *storytelling.Door {
	return &storytelling.Door{
		Code: o.Code,
		Name: textFormatter.FormatString(o.Name),
		Keys: convertKeys(o.Keys),
	}
}

func convertKey(o *proto.Key) *storytelling.Key {
	return &storytelling.Key{
		Name: textFormatter.FormatString(o.Name),
	}
}

func convertIntroduction(o *proto.Introduction) *storytelling.Introduction {
	if o == nil || (o.Text == "" && o.Audio == "") {
		return nil
	}
	return &storytelling.Introduction{
		Text:  textFormatter.FormatText(o.Text),
		Audio: o.Audio,
	}
}
