package service

import (
	"fmt"
	"sort"
	"strings"
	"sync"
	"time"
)

var backendStore = newDemoStore()

type demoStore struct {
	mu            sync.RWMutex
	Users         []UserProfile
	Content       []ContentItem
	Speakers      []Speaker
	Categories    []string
	Tags          []string
	Notifications []NotificationItem
	Comments      []CommentItem
	Audit         []AuditItem
	Files         map[string]StoredFile
}

func newDemoStore() *demoStore {
	return &demoStore{
		Users: []UserProfile{
			{ID: "demo-user-1", Name: "Демо-администратор", Login: "demo_admin", Roles: []RoleCode{RoleAdministrator, RoleEditor}, Subscriptions: []string{"Новости", "Демо-спикер 01", "медиапроизводство"}},
			{ID: "demo-user-2", Name: "Демо-редактор", Login: "demo_editor", Roles: []RoleCode{RoleEditor}, Subscriptions: []string{"Видео"}},
			{ID: "demo-user-3", Name: "Демо-пользователь", Login: "demo_user", Roles: []RoleCode{RoleUser}, Subscriptions: []string{"Аудио"}},
		},
		Content: []ContentItem{
			{ID: "demo-news-1", Title: "Демо-новость о запуске медиаплатформы", Lead: "Публичная карточка показывает, как новости и статьи будут выглядеть в едином каталоге.", Body: "Демонстрационный материал без реальных персональных данных, подразделений и брендовых материалов.", Type: ContentTypeNews, Category: "Новости", Tags: []string{"медиапроизводство", "анонс"}, Author: "Демо-редакция", PublishedAt: "2026-06-04", Visibility: VisibilityPublic, Status: ContentStatusPublished, Views: 1240, ImageTone: "from-university-700 via-university-500 to-sky-300"},
			{ID: "demo-video-1", Title: "Демо-видео: открытая лекция", Lead: "Видеоматериал с метаданными, статусом проверки, категорией и тегами.", Body: "В реальной системе здесь будет предпросмотр видео, CDN-ссылка, история модерации и аналитика просмотров.", Type: ContentTypeVideo, Category: "Видео", Tags: []string{"образование", "архив"}, Author: "Демо-медиагруппа", PublishedAt: "2026-06-09", Duration: "18:40", Visibility: VisibilityAuthenticated, Status: ContentStatusReview, Views: 382, ImageTone: "from-indigo-700 via-university-800 to-cyan-500"},
			{ID: "demo-audio-1", Title: "Демо-аудио: выпуск университетского радио", Lead: "Аудиоконтент хранится в медиатеке и связывается с публикациями, авторами и тегами.", Body: "Этот пример показывает карточку аудио без использования реального названия передачи или записи.", Type: ContentTypeAudio, Category: "Аудио", Tags: []string{"интервью", "редакция"}, Author: "Демо-редактор", PublishedAt: "2026-06-11", Duration: "32:10", Visibility: VisibilityPublic, Status: ContentStatusPublished, Views: 715, ImageTone: "from-blue-950 via-blue-700 to-emerald-300"},
			{ID: "demo-graphic-1", Title: "Демо-графика: афиша редакционного события", Lead: "Графические материалы можно фильтровать по типу, дате, категории и тегам.", Body: "Заглушка демонстрирует графический материал без копирования фотографий, логотипов или брендовых элементов.", Type: ContentTypeGraphic, Category: "Графика", Tags: []string{"анонс", "редакция"}, Author: "Демо-дизайнер", PublishedAt: "2026-06-13", Visibility: VisibilityRole, Status: ContentStatusModeration, Views: 96, ImageTone: "from-sky-400 via-blue-600 to-slate-900"},
			{ID: "demo-event-1", Title: "Демо-анонс медиавстречи со спикером", Lead: "Мероприятия показаны как тип медиаконтента до подтверждения отдельной сущности Event.", Body: "События представлены как анонсы контента, потому что отдельная сущность Event требует подтверждения заказчиком.", Type: ContentTypeEvent, Category: "Мероприятия", Tags: []string{"анонс", "интервью"}, Author: "Демо-менеджер", PublishedAt: "2026-06-17", Visibility: VisibilityPublic, Status: ContentStatusDraft, Views: 45, ImageTone: "from-university-900 via-violet-700 to-orange-300"},
		},
		Speakers: []Speaker{
			{ID: "demo-speaker-1", Name: "Демо-спикер 01", Role: "Приглашенный эксперт", Topics: []string{"медиапроизводство", "образование"}, Materials: 8, Subscribers: 132},
			{ID: "demo-speaker-2", Name: "Демо-спикер 02", Role: "Участник редакционного события", Topics: []string{"интервью", "анонс"}, Materials: 5, Subscribers: 74},
			{ID: "demo-speaker-3", Name: "Демо-спикер 03", Role: "Автор образовательных материалов", Topics: []string{"архив", "редакция"}, Materials: 12, Subscribers: 205},
		},
		Categories: []string{"Новости", "Статьи", "Видео", "Аудио", "Графика", "Мероприятия"},
		Tags:       []string{"медиапроизводство", "интервью", "анонс", "образование", "редакция", "архив"},
		Notifications: []NotificationItem{
			{ID: "demo-notification-1", Title: "Новый материал по подписке", Description: "В категории «Новости» появился демонстрационный материал.", Read: false, CreatedAt: "2026-06-13 10:20"},
			{ID: "demo-notification-2", Title: "Материал ожидает проверки", Description: "Демо-видео находится на этапе проверки перед публикацией.", Read: true, CreatedAt: "2026-06-12 16:45"},
		},
		Comments: []CommentItem{
			{ID: "demo-comment-1", ContentID: "demo-news-1", Author: "Демо-пользователь", Text: "Комментарий доступен авторизованным пользователям и может проходить модерацию.", CreatedAt: "2026-06-13 12:00"},
		},
		Audit: []AuditItem{
			{ID: "demo-audit-1", Actor: "Демо-администратор", Action: "изменил статус", Target: "Демо-видео: открытая лекция", CreatedAt: "2026-06-13 11:10"},
			{ID: "demo-audit-2", Actor: "Демо-редактор", Action: "создал черновик", Target: "Демо-анонс медиавстречи со спикером", CreatedAt: "2026-06-12 15:35"},
		},
		Files: map[string]StoredFile{},
	}
}

func (s *demoStore) userByLogin(login string) (UserProfile, bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for _, user := range s.Users {
		if user.Login == login {
			return user, true
		}
	}
	return UserProfile{}, false
}

func (s *demoStore) upsertSubscription(userID, target string) []string {
	s.mu.Lock()
	defer s.mu.Unlock()
	for index := range s.Users {
		if s.Users[index].ID == userID {
			for _, subscription := range s.Users[index].Subscriptions {
				if subscription == target {
					return append([]string(nil), s.Users[index].Subscriptions...)
				}
			}
			s.Users[index].Subscriptions = append(s.Users[index].Subscriptions, target)
			return append([]string(nil), s.Users[index].Subscriptions...)
		}
	}
	return nil
}

func (s *demoStore) addUser(login, name string) UserProfile {
	s.mu.Lock()
	defer s.mu.Unlock()
	user := UserProfile{ID: fmt.Sprintf("demo-user-%d", time.Now().UnixNano()), Name: name, Login: login, Roles: []RoleCode{RoleUser}, Subscriptions: []string{}}
	s.Users = append(s.Users, user)
	return user
}

func (s *demoStore) addContent(item ContentItem) ContentItem {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.Content = append([]ContentItem{item}, s.Content...)
	s.Audit = append([]AuditItem{{ID: fmt.Sprintf("demo-audit-%d", time.Now().UnixNano()), Actor: item.Author, Action: "создал черновик", Target: item.Title, CreatedAt: time.Now().Format("2006-01-02 15:04")}}, s.Audit...)
	return item
}

func (s *demoStore) addFile(file StoredFile) StoredFile {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.Files[file.ID] = file
	return file
}

func (s *demoStore) fileByID(id string) (StoredFile, bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	file, ok := s.Files[id]
	return file, ok
}

func (s *demoStore) patchContent(id string, patch ContentItem) (ContentItem, bool) {
	s.mu.Lock()
	defer s.mu.Unlock()
	for index, item := range s.Content {
		if item.ID != id {
			continue
		}
		if patch.Title != "" {
			item.Title = patch.Title
		}
		if patch.Lead != "" {
			item.Lead = patch.Lead
		}
		if patch.Body != "" {
			item.Body = patch.Body
		}
		if patch.Type != "" {
			item.Type = patch.Type
		}
		if patch.Category != "" {
			item.Category = patch.Category
		}
		if patch.Tags != nil {
			item.Tags = patch.Tags
		}
		if patch.Visibility != "" {
			item.Visibility = patch.Visibility
		}
		if patch.Status != "" {
			item.Status = patch.Status
		}
		if patch.MediaURL != "" {
			item.MediaURL = patch.MediaURL
		}
		if patch.MediaKind != "" {
			item.MediaKind = patch.MediaKind
		}
		if patch.MimeType != "" {
			item.MimeType = patch.MimeType
		}
		if patch.FileName != "" {
			item.FileName = patch.FileName
		}
		if patch.FileSize != 0 {
			item.FileSize = patch.FileSize
		}
		s.Content[index] = item
		return item, true
	}
	return ContentItem{}, false
}

func (s *demoStore) deleteContent(id string) bool {
	s.mu.Lock()
	defer s.mu.Unlock()
	for index, item := range s.Content {
		if item.ID == id {
			s.Content = append(s.Content[:index], s.Content[index+1:]...)
			return true
		}
	}
	return false
}

func (s *demoStore) contentByID(id string) (ContentItem, bool) {
	s.mu.Lock()
	defer s.mu.Unlock()
	for index, item := range s.Content {
		if item.ID == id {
			s.Content[index].Views++
			return s.Content[index], true
		}
	}
	return ContentItem{}, false
}

func (s *demoStore) searchContent(term, category, contentType, sortMode string) []ContentItem {
	s.mu.RLock()
	defer s.mu.RUnlock()
	term = strings.ToLower(strings.TrimSpace(term))
	items := make([]ContentItem, 0, len(s.Content))
	for _, item := range s.Content {
		joined := strings.ToLower(strings.Join(append([]string{item.Title, item.Lead, item.Body, item.Author, item.Category, string(item.Status), string(item.Type)}, item.Tags...), " "))
		if term != "" && !strings.Contains(joined, term) {
			continue
		}
		if category != "" && category != "Все" && item.Category != category {
			continue
		}
		if contentType != "" && string(item.Type) != contentType {
			continue
		}
		items = append(items, item)
	}
	sort.SliceStable(items, func(i, j int) bool {
		if sortMode == "newest" {
			return items[i].PublishedAt > items[j].PublishedAt
		}
		return items[i].Views > items[j].Views
	})
	return items
}

func (s *demoStore) addComment(contentID string, user UserProfile, text string) CommentItem {
	s.mu.Lock()
	defer s.mu.Unlock()
	comment := CommentItem{ID: fmt.Sprintf("demo-comment-%d", time.Now().UnixNano()), ContentID: contentID, Author: user.Name, Text: text, CreatedAt: time.Now().Format("2006-01-02 15:04")}
	s.Comments = append([]CommentItem{comment}, s.Comments...)
	return comment
}
