package main

import (
	"context"

	"github.com/nbd-wtf/go-nostr"
	sdk "github.com/nbd-wtf/nostr-sdk"
	. "github.com/theplant/htmlgo"
)

const buttonClass = "rounded-md text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300"

func baseHTML(inside HTMLComponent) HTMLComponent {
	navItemClass := "text-gray-600 hover:bg-gray-200 rounded-md px-3 py-2 font-medium"

	return HTML(
		Head(
			Meta().Charset("utf-8"),
			Meta().Name("viewport").Content("width=device-width, initial-scale=1"),
			Title(s.RelayName),
			Script("").Src("https://cdn.tailwindcss.com"),
			Script("").Src("https://unpkg.com/htmx.org@1.9.6"),
			Script("").Src("https://unpkg.com/hyperscript.org@0.9.12"),
		),
		Body(
			Div(
				H1(s.RelayName).Class("font-bold text-2xl"),
				P().Text(s.RelayDescription).Class("text-lg"),
			).Class("mx-auto my-6 text-center"),
			Nav(
				A().Text("information").Href("/").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
				A().Text("invite tree").Href("/users").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
				A().Text("reports").Href("/reports").Class(navItemClass).Attr("hx-boost", "true", "hx-target", "main", "hx-select", "main"),
				A().Text("").Href("#").Class(navItemClass).
					Attr("_", `
on click if my innerText is equal to "login" get window.nostr.signEvent({created_at: Math.round(Date.now()/1000), kind: 27235, tags: [['domain', "`+s.Domain+`"]], content: ''}) then get JSON.stringify(it) then set cookies['nip98'] to it otherwise call cookies.clear('nip98') end then call location.reload()

on load get cookies['nip98'] then if it is undefined set my innerText to "login" otherwise set my innerText to "logout"`),
			).Class("flex flex-1 items-center justify-center"),
			Main(inside).Class("m-4"),
		).Class("mx-4 my-6"),
	)
}

type HomePageParams struct {
	relayOwnerInfo sdk.ProfileMetadata
}

func homePageHTML(ctx context.Context, params HomePageParams) HTMLComponent {
	contact := Div()
	if s.RelayContact != "" {
		contact = Div().Text("alternative contact: " + s.RelayContact)
	}

	description := Div()
	if s.RelayDescription != "" {
		description = Div().Text("description: " + s.RelayDescription)
	}

	return Div(
		Div().Text("name: "+s.RelayName),
		description,
		contact,
		Div(
			Text("relay master: "),
			userNameComponent(params.relayOwnerInfo),
		),
		Br(),
		Div(
			Text("this relay uses"),
			A().Target("_blank").Href("https://github.com/github-tijlxyz/khatru-invite").Text("Khatru Invite").
				Class("underline"),
			Text(" which is built with "),
			A().Target("_blank").Href("https://github.com/fiatjaf/khatru").Text("Khatru").
				Class("underline"),
		).Class("text-sm"),
	)
}

type InviteTreePageParams struct {
	loggedUser string
}

func inviteTreePageHTML(ctx context.Context, params InviteTreePageParams) HTMLComponent {
	inviteForm := Div()

	if params.loggedUser != "" {
		inviteForm = Form(
			Input("pubkey").Type("text").Placeholder("npub1...").Class("w-96 rounded-md border-0 p-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600"),
			Button("invite").Class(buttonClass+" p-2 bg-white hover:bg-gray-50"),
		).Attr(
			"hx-post", "/add-to-whitelist",
			"hx-trigger", "submit",
			"hx-target", "#tree",
			"_", "on htmx:afterRequest(elt, successful) if successful and elt is I call I.reset()",
		)
	}

	return Div(
		inviteForm,
		Div(
			inviteTreeComponent(ctx, "", params.loggedUser),
		).Id("tree").Class("mt-3"),
	)
}

type ReportsPageParams struct {
	reports    chan *nostr.Event
	loggedUser string
}

func reportsPageHTML(ctx context.Context, params ReportsPageParams) HTMLComponent {
	items := make([]HTMLComponent, 0, 52)
	for report := range params.reports {
		var primaryType string
		var secondaryType string
		var relatedContent HTMLComponent

		if e := report.Tags.GetFirst([]string{"e", ""}); e != nil {
			// event report
			res, _ := sys.StoreRelay().QuerySync(ctx, nostr.Filter{IDs: []string{(*e)[1]}})
			if len(res) == 0 {
				sys.Store.DeleteEvent(ctx, report)
				continue
			}

			if len(*e) >= 3 {
				primaryType = (*e)[2]
			}

			relatedEvent := res[0]
			relatedContent = Div(
				Text("event reported: "),
				Div().Text(relatedEvent.String()).Class("text-mono"),
			)
		} else if p := report.Tags.GetFirst([]string{"p", ""}); p != nil {
			// pubkey report
			if !isPublicKeyInWhitelist((*p)[1]) {
				sys.Store.DeleteEvent(ctx, report)
				continue
			}

			if len(*p) >= 3 {
				primaryType = (*p)[2]
			}

			relatedProfile := sys.FetchOrStoreProfileMetadata(ctx, (*p)[1])
			relatedContent = Div(
				Text("profile reported: "),
				userNameComponent(relatedProfile),
			)
		} else {
			continue
		}

		reporter := sys.FetchProfileMetadata(ctx, report.PubKey)
		report := Div(
			Div(Span(primaryType).Class("font-semibold"), Text(" report")).Class("font-lg"),
			Div().Text(secondaryType),
			Div(Text("by "), userNameComponent(reporter)),
			Div().Text(report.Content).Class("p-3"),
			relatedContent,
		)

		items = append(items, report)
	}
	return baseHTML(
		Div(
			H1("reports received").Class("text-xl p-4"),
			Div(items...),
		),
	)
}