package repository

import (
	dbgen "Yimaru-Backend/gen/db"
	"Yimaru-Backend/internal/domain"
	"context"

	"github.com/jackc/pgx/v5/pgtype"
)

func (s *Store) CreateSubCourseVideo(
	ctx context.Context,
	subCourseID int64,
	title string,
	description *string,
	videoURL string,
	duration int32,
	resolution *string,
	instructorID *string,
	thumbnail *string,
	visibility *string,
	displayOrder *int32,
	status *string,
	vimeoID *string,
	vimeoEmbedURL *string,
	vimeoPlayerHTML *string,
	vimeoStatus *string,
	videoHostProvider *string,
) (domain.SubCourseVideo, error) {
	var descText, resText, instrText, thumbText, visText, statusText pgtype.Text
	var vimeoIDText, vimeoEmbedText, vimeoHTMLText, vimeoStatusText, hostProviderText pgtype.Text

	if description != nil {
		descText = pgtype.Text{String: *description, Valid: true}
	}
	if resolution != nil {
		resText = pgtype.Text{String: *resolution, Valid: true}
	}
	if instructorID != nil {
		instrText = pgtype.Text{String: *instructorID, Valid: true}
	}
	if thumbnail != nil {
		thumbText = pgtype.Text{String: *thumbnail, Valid: true}
	}
	if visibility != nil {
		visText = pgtype.Text{String: *visibility, Valid: true}
	}
	if status != nil {
		statusText = pgtype.Text{String: *status, Valid: true}
	}
	if vimeoID != nil {
		vimeoIDText = pgtype.Text{String: *vimeoID, Valid: true}
	}
	if vimeoEmbedURL != nil {
		vimeoEmbedText = pgtype.Text{String: *vimeoEmbedURL, Valid: true}
	}
	if vimeoPlayerHTML != nil {
		vimeoHTMLText = pgtype.Text{String: *vimeoPlayerHTML, Valid: true}
	}
	if vimeoStatus != nil {
		vimeoStatusText = pgtype.Text{String: *vimeoStatus, Valid: true}
	}
	if videoHostProvider != nil {
		hostProviderText = pgtype.Text{String: *videoHostProvider, Valid: true}
	}

	var dispOrder pgtype.Int4
	if displayOrder != nil {
		dispOrder = pgtype.Int4{Int32: *displayOrder, Valid: true}
	}

	row, err := s.queries.CreateSubCourseVideo(ctx, dbgen.CreateSubCourseVideoParams{
		SubCourseID:     subCourseID,
		Title:           title,
		Description:     descText,
		VideoUrl:        videoURL,
		Duration:        duration,
		Resolution:      resText,
		InstructorID:    instrText,
		Thumbnail:       thumbText,
		Visibility:      visText,
		Column10:        dispOrder,
		Column11:        statusText,
		VimeoID:         vimeoIDText,
		VimeoEmbedUrl:   vimeoEmbedText,
		VimeoPlayerHtml: vimeoHTMLText,
		Column15:        vimeoStatusText,
		Column16:        hostProviderText,
	})
	if err != nil {
		return domain.SubCourseVideo{}, err
	}

	return mapSubCourseVideoRow(row), nil
}

func (s *Store) GetSubCourseVideoByID(
	ctx context.Context,
	id int64,
) (domain.SubCourseVideo, error) {
	row, err := s.queries.GetSubCourseVideoByID(ctx, id)
	if err != nil {
		return domain.SubCourseVideo{}, err
	}

	return mapSubCourseVideoRow(row), nil
}

func (s *Store) GetVideosBySubCourse(
	ctx context.Context,
	subCourseID int64,
) ([]domain.SubCourseVideo, int64, error) {
	rows, err := s.queries.GetVideosBySubCourse(ctx, subCourseID)
	if err != nil {
		return nil, 0, err
	}

	var (
		videos     []domain.SubCourseVideo
		totalCount int64
	)

	for i, row := range rows {
		if i == 0 {
			totalCount = row.TotalCount
		}

		videos = append(videos, domain.SubCourseVideo{
			ID:              row.ID,
			SubCourseID:     row.SubCourseID,
			Title:           row.Title,
			Description:     ptrString(row.Description),
			VideoURL:        row.VideoUrl,
			Duration:        row.Duration,
			Resolution:      ptrString(row.Resolution),
			InstructorID:    ptrString(row.InstructorID),
			Thumbnail:       ptrString(row.Thumbnail),
			Visibility:      ptrString(row.Visibility),
			DisplayOrder:    row.DisplayOrder,
			IsPublished:     row.IsPublished,
			PublishDate:     ptrTimestamptz(row.PublishDate),
			Status:          row.Status,
			VimeoID:         ptrString(row.VimeoID),
			VimeoEmbedURL:   ptrString(row.VimeoEmbedUrl),
			VimeoPlayerHTML: ptrString(row.VimeoPlayerHtml),
			VimeoStatus:     ptrString(row.VimeoStatus),
		})
	}

	return videos, totalCount, nil
}

func (s *Store) GetPublishedVideosBySubCourse(
	ctx context.Context,
	subCourseID int64,
) ([]domain.SubCourseVideo, error) {
	rows, err := s.queries.GetPublishedVideosBySubCourse(ctx, subCourseID)
	if err != nil {
		return nil, err
	}

	videos := make([]domain.SubCourseVideo, 0, len(rows))
	for _, row := range rows {
		videos = append(videos, mapSubCourseVideoRow(row))
	}

	return videos, nil
}

func (s *Store) PublishSubCourseVideo(
	ctx context.Context,
	videoID int64,
) error {
	return s.queries.PublishSubCourseVideo(ctx, videoID)
}

func (s *Store) UpdateSubCourseVideo(
	ctx context.Context,
	id int64,
	title *string,
	description *string,
	videoURL *string,
	duration *int32,
	resolution *string,
	visibility *string,
	thumbnail *string,
	displayOrder *int32,
	status *string,
) error {
	var titleVal, descVal, urlVal, resVal, visVal, thumbVal, statusVal string
	var durationVal, dispOrderVal int32

	if title != nil {
		titleVal = *title
	}
	if description != nil {
		descVal = *description
	}
	if videoURL != nil {
		urlVal = *videoURL
	}
	if duration != nil {
		durationVal = *duration
	}
	if resolution != nil {
		resVal = *resolution
	}
	if visibility != nil {
		visVal = *visibility
	}
	if thumbnail != nil {
		thumbVal = *thumbnail
	}
	if displayOrder != nil {
		dispOrderVal = *displayOrder
	}
	if status != nil {
		statusVal = *status
	}

	return s.queries.UpdateSubCourseVideo(ctx, dbgen.UpdateSubCourseVideoParams{
		Title:        titleVal,
		Description:  pgtype.Text{String: descVal, Valid: description != nil},
		VideoUrl:     urlVal,
		Duration:     durationVal,
		Resolution:   pgtype.Text{String: resVal, Valid: resolution != nil},
		Visibility:   pgtype.Text{String: visVal, Valid: visibility != nil},
		Thumbnail:    pgtype.Text{String: thumbVal, Valid: thumbnail != nil},
		DisplayOrder: dispOrderVal,
		Status:       statusVal,
		ID:           id,
	})
}

func (s *Store) ArchiveSubCourseVideo(
	ctx context.Context,
	id int64,
) error {
	return s.queries.ArchiveSubCourseVideo(ctx, id)
}

func (s *Store) DeleteSubCourseVideo(
	ctx context.Context,
	id int64,
) error {
	return s.queries.DeleteSubCourseVideo(ctx, id)
}

func mapSubCourseVideoRow(row dbgen.SubCourseVideo) domain.SubCourseVideo {
	return domain.SubCourseVideo{
		ID:              row.ID,
		SubCourseID:     row.SubCourseID,
		Title:           row.Title,
		Description:     ptrString(row.Description),
		VideoURL:        row.VideoUrl,
		Duration:        row.Duration,
		Resolution:      ptrString(row.Resolution),
		InstructorID:    ptrString(row.InstructorID),
		Thumbnail:       ptrString(row.Thumbnail),
		Visibility:      ptrString(row.Visibility),
		DisplayOrder:    row.DisplayOrder,
		IsPublished:     row.IsPublished,
		PublishDate:     ptrTimestamptz(row.PublishDate),
		Status:          row.Status,
		VimeoID:         ptrString(row.VimeoID),
		VimeoEmbedURL:   ptrString(row.VimeoEmbedUrl),
		VimeoPlayerHTML: ptrString(row.VimeoPlayerHtml),
		VimeoStatus:     ptrString(row.VimeoStatus),
	}
}

func (s *Store) UpdateVimeoStatus(ctx context.Context, videoID int64, status string) error {
	return s.queries.UpdateVimeoStatus(ctx, dbgen.UpdateVimeoStatusParams{
		VimeoStatus: pgtype.Text{String: status, Valid: true},
		ID:          videoID,
	})
}

func (s *Store) GetVideoByVimeoID(ctx context.Context, vimeoID string) (domain.SubCourseVideo, error) {
	row, err := s.queries.GetVideosByVimeoID(ctx, pgtype.Text{String: vimeoID, Valid: true})
	if err != nil {
		return domain.SubCourseVideo{}, err
	}
	return mapSubCourseVideoRow(row), nil
}
