package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"text/tabwriter"

	"git.d-ma.be/mathias/tapir/internal/adapters/store"
)

// runList prints the user's stored summaries as a table, most recent first.
// Read-only. Usage: tapir list [-limit N].
func runList(ctx context.Context, args []string) error {
	fs := flag.NewFlagSet("list", flag.ContinueOnError)
	limit := fs.Int("limit", 50, "maximum number of summaries to show")
	if err := fs.Parse(args); err != nil {
		return err
	}

	s, userID, closeFn, err := openStoreFromEnv(ctx)
	if err != nil {
		return err
	}
	defer closeFn()

	rows, err := s.ListSummaries(ctx, userID, *limit)
	if err != nil {
		return err
	}
	return formatList(os.Stdout, rows)
}

// formatList renders rows as an aligned table. Pure: no DB, no env — so the
// column layout and fallbacks are unit-testable without Postgres. Title falls
// back to the video id and Channel to "-" when the videos row is absent.
func formatList(w io.Writer, rows []store.SummaryRow) error {
	if len(rows) == 0 {
		_, err := fmt.Fprintln(w, "no summaries yet")
		return err
	}

	// Writes to the tabwriter buffer; any error surfaces on Flush.
	tw := tabwriter.NewWriter(w, 0, 4, 2, ' ', 0)
	_, _ = fmt.Fprintln(tw, "DATE\tTITLE\tCHANNEL\tAI\tFALLBACK")
	for _, r := range rows {
		_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\n",
			listDate(r),
			truncate(displayTitle(r), 60),
			orDash(r.Channel),
			orDash(r.AIProvider),
			fallbackFlag(r.FallbackUsed),
		)
	}
	return tw.Flush()
}

// listDate prefers the video's publish date; absent that, when the summary was
// created. Date only — the table is for scanning, not timestamps.
func listDate(r store.SummaryRow) string {
	t := r.PublishedAt
	if t.IsZero() {
		t = r.CreatedAt
	}
	if t.IsZero() {
		return "-"
	}
	return t.Format("2006-01-02")
}

// displayTitle falls back to the video id when no title is stored, so a summary
// produced before the run loop populated videos is still identifiable.
func displayTitle(r store.SummaryRow) string {
	if strings.TrimSpace(r.Title) != "" {
		return r.Title
	}
	return r.VideoID
}

func fallbackFlag(used bool) string {
	if used {
		return "yes"
	}
	return "no"
}

func orDash(s string) string {
	if strings.TrimSpace(s) == "" {
		return "-"
	}
	return s
}

func truncate(s string, max int) string {
	if len(s) <= max {
		return s
	}
	if max <= 1 {
		return s[:max]
	}
	return s[:max-1] + "…"
}
