package handlers

import (
	"fmt"
	"net/http"
	"strings"

	"git.soup.land/soup/lookbook/internal/components"
	"git.soup.land/soup/lookbook/internal/data/image"
	"git.soup.land/soup/lookbook/internal/data/item"
	"git.soup.land/soup/lookbook/internal/data/tag"
	"git.soup.land/soup/lookbook/internal/services"
	"git.soup.land/soup/sxgo/ssr"
)

type itemPageData struct {
	Item        item.Row
	Images      []image.Row
	TagNames    []string
	AllTagNames []string
	HasAuth     bool
}

func (d itemPageData) Render(sw *ssr.Writer) error {
	return sw.Tmpl(d, `
<section class="detail">
	<div>
		{{if .Images}}
		<img src="/images/{{(index .Images 0).ID}}" alt="{{.Item.Title}}">
		{{else}}
		<div class="notice">No preview image cached.</div>
		{{end}}
	</div>
	<div class="meta">
		<h1>{{if .Item.Title}}{{.Item.Title}}{{else}}{{.Item.SourceURL}}{{end}}</h1>
		{{if .Item.SiteName}}<div>{{.Item.SiteName}}</div>{{end}}
		{{if .Item.Description}}<p>{{.Item.Description}}</p>{{end}}
		<a href="{{.Item.SourceURL}}" target="_blank" rel="noreferrer">{{.Item.SourceURL}}</a>

		<div>
			<strong>Tags</strong>
			<div class="tag-list" data-tag-list>
				{{range .TagNames}}
				<span class="tag-chip">{{.}}</span>
				{{else}}
				<span class="tag-chip">No tags</span>
				{{end}}
			</div>
			<button type="button" class="ghost" data-tag-toggle data-auth-required {{if not .HasAuth}}hidden{{end}}>Edit tags</button>
		</div>

		<div class="tag-editor" data-tag-editor data-auth-required hidden {{if not .HasAuth}}hidden{{end}}>
			<form method="POST" action="/items/{{.Item.ID}}/tags" data-tag-form>
				<input type="text" name="tags" value="{{range $i, $tag := .TagNames}}{{if $i}}, {{end}}{{$tag}}{{end}}" data-tag-input>
				<button type="submit">Save tags</button>
			</form>
			<div class="tag-suggestions" data-tag-suggestions data-tags='{{json .AllTagNames}}'></div>
		</div>

		<div class="actions" data-auth-required {{if not .HasAuth}}hidden{{end}}>
			<form method="POST" action="/items/{{.Item.ID}}/refresh">
				<button type="submit">Refresh metadata</button>
			</form>
			<form method="POST" action="/items/{{.Item.ID}}/delete">
				<button type="submit">Delete</button>
			</form>
		</div>
	</div>
</section>
`)
}

func HandleGetItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error {
	id, err := parseID(r.PathValue("id"))
	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return nil
	}

	row, err := item.QFindByID(r.Context(), rc.DB, id)
	if err != nil {
		return fmt.Errorf("find item: %w", err)
	}
	if row == nil {
		http.NotFound(w, r)
		return nil
	}

	images, err := image.QListByItem(r.Context(), rc.DB, id)
	if err != nil {
		return fmt.Errorf("list images: %w", err)
	}

	tags, err := tag.QListByItem(r.Context(), rc.DB, id)
	if err != nil {
		return fmt.Errorf("list item tags: %w", err)
	}

	allTags, err := tag.QList(r.Context(), rc.DB)
	if err != nil {
		return fmt.Errorf("list tags: %w", err)
	}

	var tagNames []string
	for _, row := range tags {
		tagNames = append(tagNames, row.Name)
	}

	var allTagNames []string
	for _, row := range allTags {
		allTagNames = append(allTagNames, row.Name)
	}

	authed, err := isAuthenticated(r, rc)
	if err != nil {
		return fmt.Errorf("auth status: %w", err)
	}

	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	sw := ssr.NewWriter(w, rc.TmplCache)

	data := itemPageData{
		Item:        *row,
		Images:      images,
		TagNames:    tagNames,
		AllTagNames: allTagNames,
		HasAuth:     authed,
	}

	return components.Page{
		Title:   "Item",
		Content: data,
		ShowNav: true,
		HasAuth: authed,
	}.Render(sw)
}

func HandlePostItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error {
	if !requireAuth(w, r, rc) {
		return nil
	}

	if err := r.ParseForm(); err != nil {
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return nil
	}

	sourceURL := strings.TrimSpace(r.FormValue("url"))
	if sourceURL == "" {
		http.Error(w, "URL required", http.StatusBadRequest)
		return nil
	}

	_, err := services.CreateItemFromURL(r.Context(), rc.DB, sourceURL)
	if err != nil {
		return fmt.Errorf("create item: %w", err)
	}

	http.Redirect(w, r, "/", http.StatusSeeOther)
	return nil
}

func HandlePostItemTags(rc *RequestContext, w http.ResponseWriter, r *http.Request) error {
	if !requireAuth(w, r, rc) {
		return nil
	}

	id, err := parseID(r.PathValue("id"))
	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return nil
	}

	if err := r.ParseForm(); err != nil {
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return nil
	}

	tags := parseTags(r.FormValue("tags"))
	if err := tag.QReplaceItemTags(r.Context(), rc.DB, id, tags); err != nil {
		return fmt.Errorf("update tags: %w", err)
	}

	w.WriteHeader(http.StatusNoContent)
	return nil
}

func HandleDeleteItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error {
	if !requireAuth(w, r, rc) {
		return nil
	}

	id, err := parseID(r.PathValue("id"))
	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return nil
	}

	if err := item.QSoftDelete(r.Context(), rc.DB, id); err != nil {
		return fmt.Errorf("delete item: %w", err)
	}

	http.Redirect(w, r, "/", http.StatusSeeOther)
	return nil
}

func HandleRefreshItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error {
	if !requireAuth(w, r, rc) {
		return nil
	}

	id, err := parseID(r.PathValue("id"))
	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return nil
	}

	row, err := item.QFindByID(r.Context(), rc.DB, id)
	if err != nil {
		return fmt.Errorf("find item: %w", err)
	}
	if row == nil {
		http.NotFound(w, r)
		return nil
	}

	if err := services.RefreshItemFromURL(r.Context(), rc.DB, *row); err != nil {
		return fmt.Errorf("refresh item: %w", err)
	}

	http.Redirect(w, r, fmt.Sprintf("/items/%d", id), http.StatusSeeOther)
	return nil
}

func parseTags(value string) []string {
	var tags []string
	for _, tagValue := range strings.Split(value, ",") {
		clean := strings.TrimSpace(tagValue)
		if clean == "" {
			continue
		}
		tags = append(tags, clean)
	}
	return tags
}
