package usecase

import (
	"context"
	"strings"

	"haixun-backend/internal/model/content_matrix/domain/entity"
	domrepo "haixun-backend/internal/model/content_matrix/domain/repository"
	domusecase "haixun-backend/internal/model/content_matrix/domain/usecase"

	app "haixun-backend/internal/library/errors"
	"haixun-backend/internal/library/errors/code"
	libmongo "haixun-backend/internal/library/mongo"
)

type contentMatrixUseCase struct {
	repo domrepo.Repository
}

func NewUseCase(repo domrepo.Repository) domusecase.UseCase {
	return &contentMatrixUseCase{repo: repo}
}

func (u *contentMatrixUseCase) Get(ctx context.Context, tenantID, ownerUID, brandID string) (*domusecase.MatrixSummary, error) {
	if err := requireActor(tenantID, ownerUID, brandID); err != nil {
		return nil, err
	}
	record, err := u.repo.GetByBrand(ctx, tenantID, ownerUID, brandID)
	if err != nil {
		return nil, err
	}
	if record == nil {
		return &domusecase.MatrixSummary{BrandID: brandID, Rows: []domusecase.Row{}}, nil
	}
	return toSummary(record), nil
}

func (u *contentMatrixUseCase) Upsert(ctx context.Context, req domusecase.UpsertRequest) (*domusecase.MatrixSummary, error) {
	if err := requireActor(req.TenantID, req.OwnerUID, req.BrandID); err != nil {
		return nil, err
	}
	rows := make([]entity.Row, 0, len(req.Rows))
	for _, row := range req.Rows {
		rows = append(rows, entity.Row{
			SortOrder:        row.SortOrder,
			SearchTag:        row.SearchTag,
			Angle:            row.Angle,
			Hook:             row.Hook,
			Text:             row.Text,
			ReferenceNotes:   row.ReferenceNotes,
			SourcePermalinks: row.SourcePermalinks,
			Rationale:        row.Rationale,
		})
	}
	record := &entity.ContentMatrix{
		TenantID:    req.TenantID,
		OwnerUID:    req.OwnerUID,
		BrandID:     req.BrandID,
		Rows:        rows,
		GeneratedAt: req.GeneratedAt,
	}
	saved, err := u.repo.UpsertByBrand(ctx, record)
	if err != nil {
		return nil, err
	}
	return toSummary(saved), nil
}

func requireActor(tenantID, ownerUID, brandID string) error {
	if strings.TrimSpace(tenantID) == "" || strings.TrimSpace(ownerUID) == "" {
		return app.For(code.Brand).InputMissingRequired("tenant_id and uid are required")
	}
	if strings.TrimSpace(brandID) == "" {
		return app.For(code.Brand).InputMissingRequired("brand id is required")
	}
	return nil
}

func toSummary(record *entity.ContentMatrix) *domusecase.MatrixSummary {
	if record == nil {
		return nil
	}
	rows := make([]domusecase.Row, 0, len(record.Rows))
	for _, row := range record.Rows {
		rows = append(rows, domusecase.Row{
			SortOrder:        row.SortOrder,
			SearchTag:        row.SearchTag,
			Angle:            row.Angle,
			Hook:             row.Hook,
			Text:             row.Text,
			ReferenceNotes:   row.ReferenceNotes,
			SourcePermalinks: row.SourcePermalinks,
			Rationale:        row.Rationale,
		})
	}
	return &domusecase.MatrixSummary{
		ID:          record.ID,
		BrandID:     libmongo.ResolveBrandID(record.BrandID, record.LegacyPersonaID),
		Rows:        rows,
		GeneratedAt: record.GeneratedAt,
		CreateAt:    record.CreateAt,
		UpdateAt:    record.UpdateAt,
	}
}
