package types

import "apps/backend/internal/module/studio/domain"

func PersonaFromDomain(p *domain.Persona) PersonaPublic {
	if p == nil {
		return PersonaPublic{}
	}
	return PersonaPublic{
		Id: p.ID, Name: p.Name, Brief: p.Brief, Status: p.Status,
		Style: PersonaStylePublic{
			Draft: PersonaDraftPublic{
				Identity: p.Style.Draft.Identity, Tone: p.Style.Draft.Tone,
				Audience: p.Style.Draft.Audience, Hooks: p.Style.Draft.Hooks,
				LanguageFingerprint: p.Style.Draft.LanguageFingerprint,
				Rhythm:              p.Style.Draft.Rhythm, Punctuation: p.Style.Draft.Punctuation,
				ContentPatterns:      p.Style.Draft.ContentPatterns,
				KnowledgeTranslation: p.Style.Draft.KnowledgeTranslation,
				CtaStyle:             p.Style.Draft.CtaStyle, Examples: p.Style.Draft.Examples,
				Avoid: p.Style.Draft.Avoid,
			},
			DraftText: p.Style.DraftText, Source: p.Style.Source,
			BenchmarkUsername: p.Style.BenchmarkUsername, SourceLabel: p.Style.SourceLabel,
			SampleCount: p.Style.SampleCount, AnalyzedAt: p.Style.AnalyzedAt,
			SamplePreviews: p.Style.SamplePreviews,
			Dimensions:     styleDimensionsFromDomain(p.Style.Dimensions),
		},
		Guard: PersonaGuardPublic{
			Avoid: p.Guard.Avoid, MaxChars: p.Guard.MaxChars, BanAiTone: p.Guard.BanAiTone,
		},
		Voice: p.Voice, Notes: p.Notes,
		LearningSummary: p.LearningSummary, LearningVersion: p.LearningVersion,
		LearnedFromPostsCount: p.LearnedFromPostsCount, LastLearnedAt: p.LastLearnedAt,
		CreatedAt: p.CreatedAt, UpdatedAt: p.UpdatedAt,
	}
}

func styleDimensionsFromDomain(in map[string]domain.StyleDimension) map[string]StyleDimensionPublic {
	if len(in) == 0 {
		return nil
	}
	out := make(map[string]StyleDimensionPublic, len(in))
	for k, v := range in {
		out[k] = StyleDimensionPublic{Summary: v.Summary, Evidence: v.Evidence}
	}
	return out
}

func styleDimensionsToDomain(in map[string]StyleDimensionPublic) map[string]domain.StyleDimension {
	if len(in) == 0 {
		return nil
	}
	out := make(map[string]domain.StyleDimension, len(in))
	for k, v := range in {
		out[k] = domain.StyleDimension{Summary: v.Summary, Evidence: v.Evidence}
	}
	return out
}

func PersonaToDomain(req *PersonaSaveReq, ownerUID int64) *domain.Persona {
	p := &domain.Persona{
		ID: req.Id, OwnerUID: ownerUID, Name: req.Name, Brief: req.Brief, Status: req.Status,
		Voice: req.Voice, Notes: req.Notes,
		Style: domain.PersonaStyle{
			Draft: domain.PersonaDraft{
				Identity: req.Style.Draft.Identity, Tone: req.Style.Draft.Tone,
				Audience: req.Style.Draft.Audience, Hooks: req.Style.Draft.Hooks,
				LanguageFingerprint: req.Style.Draft.LanguageFingerprint,
				Rhythm:              req.Style.Draft.Rhythm, Punctuation: req.Style.Draft.Punctuation,
				ContentPatterns:      req.Style.Draft.ContentPatterns,
				KnowledgeTranslation: req.Style.Draft.KnowledgeTranslation,
				CtaStyle:             req.Style.Draft.CtaStyle, Examples: req.Style.Draft.Examples,
				Avoid: req.Style.Draft.Avoid,
			},
			DraftText: req.Style.DraftText, Source: req.Style.Source,
			BenchmarkUsername: req.Style.BenchmarkUsername, SourceLabel: req.Style.SourceLabel,
			SampleCount: req.Style.SampleCount, AnalyzedAt: req.Style.AnalyzedAt,
			SamplePreviews: req.Style.SamplePreviews,
			Dimensions:     styleDimensionsToDomain(req.Style.Dimensions),
		},
		Guard: domain.PersonaGuard{
			Avoid: req.Guard.Avoid, MaxChars: req.Guard.MaxChars, BanAiTone: req.Guard.BanAiTone,
		},
	}
	return p
}

func PlayFromDomain(p *domain.Play) PlayPublic {
	if p == nil {
		return PlayPublic{}
	}
	steps := make([]PlayStepPublic, 0, len(p.Steps))
	for _, s := range p.Steps {
		steps = append(steps, PlayStepPublic{
			Id: s.ID, SortOrder: s.SortOrder, Kind: s.Kind, AccountId: s.AccountID,
			Text: s.Text, DelayFromPreviousSec: s.DelayFromPreviousSec,
			PersonaId: s.PersonaID, BrandId: s.BrandID, ImageUrls: s.ImageURLs,
		})
	}
	out := PlayPublic{
		Id: p.ID, Title: p.Title, Topic: p.Topic, Status: p.Status,
		LeadAccountId: p.LeadAccountID, CastAccountIds: p.CastAccountIDs,
		TargetOwnPostId: p.TargetOwnPostID, Steps: steps,
		ScheduleStartAt: p.ScheduleStartAt, IntervalMinutes: p.IntervalMinutes,
		CreatedAt: p.CreatedAt, UpdatedAt: p.UpdatedAt,
	}
	if p.TargetExternal != nil {
		out.TargetExternal = ExternalTargetPublic{
			Url: p.TargetExternal.URL, RawUrl: p.TargetExternal.RawURL,
			Shortcode: p.TargetExternal.Shortcode, AuthorUsername: p.TargetExternal.AuthorUsername,
			TextPreview: p.TargetExternal.TextPreview, MediaId: p.TargetExternal.MediaID,
			ResolvedAt: p.TargetExternal.ResolvedAt,
		}
	}
	return out
}

func PlayToDomain(req *PlaySaveReq, ownerUID int64) *domain.Play {
	steps := make([]domain.PlayStep, 0, len(req.Steps))
	for _, s := range req.Steps {
		steps = append(steps, domain.PlayStep{
			ID: s.Id, SortOrder: s.SortOrder, Kind: s.Kind, AccountID: s.AccountId,
			Text: s.Text, DelayFromPreviousSec: s.DelayFromPreviousSec,
			PersonaID: s.PersonaId, BrandID: s.BrandId, ImageURLs: s.ImageUrls,
		})
	}
	p := &domain.Play{
		ID: req.Id, OwnerUID: ownerUID, Title: req.Title, Topic: req.Topic, Status: req.Status,
		LeadAccountID: req.LeadAccountId, CastAccountIDs: req.CastAccountIds,
		TargetOwnPostID: req.TargetOwnPostId, Steps: steps,
		ScheduleStartAt: req.ScheduleStartAt, IntervalMinutes: req.IntervalMinutes,
	}
	if req.TargetExternal.Url != "" {
		p.TargetExternal = &domain.ExternalTarget{
			URL: req.TargetExternal.Url, RawURL: req.TargetExternal.RawUrl,
			Shortcode: req.TargetExternal.Shortcode, AuthorUsername: req.TargetExternal.AuthorUsername,
			TextPreview: req.TargetExternal.TextPreview, MediaID: req.TargetExternal.MediaId,
			ResolvedAt: req.TargetExternal.ResolvedAt,
		}
	}
	return p
}

func ExternalFromDomain(t *domain.ExternalTarget) ExternalTargetPublic {
	if t == nil {
		return ExternalTargetPublic{}
	}
	return ExternalTargetPublic{
		Url: t.URL, RawUrl: t.RawURL, Shortcode: t.Shortcode, AuthorUsername: t.AuthorUsername,
		TextPreview: t.TextPreview, MediaId: t.MediaID, ResolvedAt: t.ResolvedAt,
	}
}

func OutboxFromDomain(b *domain.OutboxBundle) OutboxPublic {
	if b == nil {
		return OutboxPublic{}
	}
	steps := make([]OutboxStepPublic, 0, len(b.Steps))
	for _, s := range b.Steps {
		steps = append(steps, OutboxStepPublic{
			Id: s.ID, StepId: s.StepID, SortOrder: s.SortOrder, Kind: s.Kind,
			AccountId: s.AccountID, Text: s.Text, Status: s.Status, Error: s.Error,
			ScheduledAt: s.ScheduledAt, PublishedAt: s.PublishedAt,
		})
	}
	return OutboxPublic{
		Id: b.ID, PlayId: b.PlayID, Title: b.Title, Status: b.Status,
		Steps: steps, CreatedAt: b.CreatedAt, UpdatedAt: b.UpdatedAt,
	}
}

func OwnPostFromDomain(p *domain.OwnPost) OwnPostPublic {
	if p == nil {
		return OwnPostPublic{}
	}
	replies := make([]OwnPostReplyPublic, 0, len(p.Replies))
	for _, r := range p.Replies {
		replies = append(replies, OwnPostReplyPublic{
			Id: r.ID, Username: r.Username, Text: r.Text, CreatedAt: r.CreatedAt,
			LikeCount: r.LikeCount, ReplyStatus: r.ReplyStatus, RepliedBy: r.RepliedBy,
			RepliedAt: r.RepliedAt, ParentReplyId: r.ParentReplyID, IsMine: r.IsMine,
			HideStatus: r.HideStatus,
		})
	}
	return OwnPostPublic{
		Id: p.ID, AccountId: p.AccountID, MediaId: p.MediaID, Text: p.Text,
		MediaType: p.MediaType, MediaUrl: p.MediaURL, ThumbnailUrl: p.ThumbnailURL,
		Permalink: p.Permalink, Shortcode: p.Shortcode, TopicTag: p.TopicTag,
		LikeCount: p.LikeCount, ReplyCount: p.ReplyCount, RepostCount: p.RepostCount,
		QuoteCount: p.QuoteCount, ViewCount: p.ViewCount, ShareCount: p.ShareCount,
		InsightsStatus: p.InsightsStatus, FormulaSummary: p.FormulaSummary,
		Insight: p.Insight, FormulaDetail: p.FormulaDetail, Replies: replies,
		PublishedAt: p.PublishedAt, ReplyControl: p.ReplyControl,
	}
}

func MentionFromDomain(m *domain.Mention) MentionPublic {
	if m == nil {
		return MentionPublic{}
	}
	return MentionPublic{
		Id: m.ID, AccountId: m.AccountID, MediaId: m.MediaID,
		FromUsername: m.FromUsername, Text: m.Text,
		ContextSnippet: m.ContextSnippet, Permalink: m.Permalink,
		Status: m.Status, DraftText: m.DraftText, CreatedAt: m.CreatedAt,
	}
}

func ViralFromDomain(v *domain.ViralAnalysis) ViralAnalysisPublic {
	if v == nil {
		return ViralAnalysisPublic{}
	}
	return ViralAnalysisPublic{
		Hooks: v.Hooks, Structure: v.Structure, Emotion: v.Emotion,
		Summary: v.Summary, Cta: v.CTA, Copyable: v.Copyable, Risks: v.Risks,
	}
}
