/*
 * Copyright Â© 2018-2019, 2021 Musing Studio LLC.
 *
 * This file is part of WriteFreely.
 *
 * WriteFreely is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, included
 * in the LICENSE file in this source code package.
 */

package writefreely

import (
	"github.com/writeas/web-core/log"
	"github.com/writefreely/go-nodeinfo"
	"github.com/writefreely/writefreely/config"
	"strings"
)

type nodeInfoResolver struct {
	cfg *config.Config
	db  *datastore
}

func nodeInfoConfig(db *datastore, cfg *config.Config) *nodeinfo.Config {
	name := cfg.App.SiteName
	desc := cfg.App.SiteDesc
	if desc == "" {
		desc = "Minimal, federated blogging platform."
	}
	if cfg.App.SingleUser {
		// Fetch blog information, instead
		coll, err := db.GetCollectionByID(1)
		if err == nil {
			desc = coll.Description
		}
	}
	return &nodeinfo.Config{
		BaseURL: cfg.App.Host,
		InfoURL: "/api/nodeinfo",

		Metadata: nodeinfo.Metadata{
			NodeName:        name,
			NodeDescription: desc,
			Private:         cfg.App.Private,
			Software: nodeinfo.SoftwareMeta{
				HomePage: softwareURL,
				GitHub:   "https://github.com/writefreely/writefreely",
				Follow:   "https://writing.exchange/@writefreely",
			},
			MaxBlogs:     cfg.App.MaxBlogs,
			PublicReader: cfg.App.LocalTimeline,
			Invites:      cfg.App.UserInvites != "",
		},
		Protocols: []nodeinfo.NodeProtocol{
			nodeinfo.ProtocolActivityPub,
		},
		Services: nodeinfo.Services{
			Inbound: []nodeinfo.NodeService{},
			Outbound: []nodeinfo.NodeService{
				nodeinfo.ServiceRSS,
			},
		},
		Software: nodeinfo.SoftwareInfo{
			Name:    strings.ToLower(serverSoftware),
			Version: softwareVer,
		},
	}
}

func (r nodeInfoResolver) IsOpenRegistration() (bool, error) {
	return r.cfg.App.OpenRegistration, nil
}

func (r nodeInfoResolver) Usage() (nodeinfo.Usage, error) {
	var collCount, postCount int64
	var activeHalfYear, activeMonth int
	var err error
	collCount, err = r.db.GetTotalCollections()
	if err != nil {
		collCount = 0
	}
	postCount, err = r.db.GetTotalPosts()
	if err != nil {
		log.Error("Unable to fetch post counts: %v", err)
	}

	if r.cfg.App.PublicStats {
		// Display bi-yearly / monthly stats
		err = r.db.QueryRow(`SELECT COUNT(*) FROM (
SELECT DISTINCT collection_id
FROM posts
INNER JOIN collections c
ON collection_id = c.id
WHERE collection_id IS NOT NULL
	AND updated > DATE_SUB(NOW(), INTERVAL 6 MONTH)) co`).Scan(&activeHalfYear)
		if err != nil {
			log.Error("Failed getting 6-month active user stats: %s", err)
		}

		err = r.db.QueryRow(`SELECT COUNT(*) FROM (
SELECT DISTINCT collection_id
FROM posts
INNER JOIN collections c
ON collection_id = c.id
WHERE collection_id IS NOT NULL
	AND updated > DATE_SUB(NOW(), INTERVAL 1 MONTH)) co`).Scan(&activeMonth)
		if err != nil {
			log.Error("Failed getting 1-month active user stats: %s", err)
		}
	}

	return nodeinfo.Usage{
		Users: nodeinfo.UsageUsers{
			Total:          int(collCount),
			ActiveHalfYear: activeHalfYear,
			ActiveMonth:    activeMonth,
		},
		LocalPosts: int(postCount),
	}, nil
}
