package usecase

import (
	"context"
	"fmt"
	"path"

	"source.toby3d.me/toby3d/home/internal/domain"
	"source.toby3d.me/toby3d/home/internal/page"
	"source.toby3d.me/toby3d/home/internal/static"
	"source.toby3d.me/toby3d/home/internal/urlutil"
)

type pageUseCase struct {
	pages   page.Repository
	statics static.Repository
}

func NewPageUseCase(pages page.Repository, statics static.Repository) page.UseCase {
	return &pageUseCase{
		pages:   pages,
		statics: statics,
	}
}

func (ucase *pageUseCase) Do(ctx context.Context, lang domain.Language, p string) (*domain.Page, error) {
	ext := path.Ext(p)
	if ext == ".html" {
		p = p[:len(p)-len(ext)]
	}

	hasTrailingSlash := p[len(p)-1] == '/'
	head, tail := urlutil.ShiftPath(p)
	targets := []string{path.Join(head, tail)}

	if tail == "/" {
		if hasTrailingSlash || ext == "" {
			targets = append([]string{path.Join(head, "index")}, targets...)
		}

		targets = append(targets, head)
	}

	for i := range targets {
		out, err := ucase.pages.Get(ctx, lang, targets[i])
		if err != nil {
			continue
		}

		if out.Resources, _, err = ucase.statics.Fetch(ctx, out.File.Dir()+"*"); err != nil {
			return out, nil
		}

		for _, res := range out.Resources.GetType(domain.ResourceTypePage) {
			if res.File.TranslationBaseName() != out.File.TranslationBaseName() {
				continue
			}

			translation, err := ucase.pages.Get(ctx, res.File.Language, targets[i])
			if err != nil {
				continue
			}

			out.Translations = append(out.Translations, translation)
		}

		return out, nil
	}

	return nil, fmt.Errorf("cannot find page on path '%s': %w", p, page.ErrNotExist)
}
