// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package lunatask

import (
	"context"
	"fmt"
	"net/http"
	"time"
)

// JournalEntry is a daily journal entry. Name and Content are encrypted
// client-side and will be null when read back from the API.
type JournalEntry struct {
	ID        string    `json:"id"`
	DateOn    Date      `json:"date_on"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

// createJournalEntryRequest defines a new journal entry for JSON serialization.
type createJournalEntryRequest struct {
	// DateOn is the date for the journal entry (required).
	DateOn Date `json:"date_on"`
	// Name is the title for the entry (optional, defaults to weekday name like "Tuesday, July 1st").
	Name *string `json:"name,omitempty"`
	// Content is the Markdown content of the entry (optional).
	Content *string `json:"content,omitempty"`
}

// journalEntryResponse wraps a single journal entry from the API.
type journalEntryResponse struct {
	JournalEntry JournalEntry `json:"journal_entry"`
}

// JournalEntryBuilder constructs and creates a journal entry via method chaining.
// Journal content is encrypted client-side; the API accepts it on create but
// returns null on read.
//
//	entry, err := client.NewJournalEntry(lunatask.Today()).
//		WithContent("Shipped the new feature!").
//		Create(ctx)
type JournalEntryBuilder struct {
	client *Client
	req    createJournalEntryRequest
}

// NewJournalEntry starts building a journal entry for the given date.
func (c *Client) NewJournalEntry(date Date) *JournalEntryBuilder {
	return &JournalEntryBuilder{client: c, req: createJournalEntryRequest{DateOn: date}}
}

// WithName sets the entry's title. Defaults to the weekday name if omitted.
func (b *JournalEntryBuilder) WithName(name string) *JournalEntryBuilder {
	b.req.Name = &name

	return b
}

// WithContent sets the Markdown body.
func (b *JournalEntryBuilder) WithContent(content string) *JournalEntryBuilder {
	b.req.Content = &content

	return b
}

// Create sends the journal entry to Lunatask. Returns the created entry's metadata;
// Name and Content won't round-trip due to E2EE.
func (b *JournalEntryBuilder) Create(ctx context.Context) (*JournalEntry, error) {
	if b.req.DateOn.IsZero() {
		return nil, fmt.Errorf("%w: date_on is required", ErrBadRequest)
	}

	resp, _, err := doJSON[journalEntryResponse](ctx, b.client, http.MethodPost, "/journal_entries", b.req)
	if err != nil {
		return nil, err
	}

	return &resp.JournalEntry, nil
}
