package status

import (
	"context"
	"os"
	"path/filepath"
	"testing"
	"time"
)

func TestAntigravityCheckerRequestsUsageAndModel(t *testing.T) {
	dir := t.TempDir()
	fakeAgy := filepath.Join(dir, "agy")

	script := `#!/usr/bin/env sh
printf 'Antigravity CLI v0.42.0\n'
printf '? for shortcuts\n'
sleep 0.1

IFS= read -r command
cmd="${command#?}"
if [ "$cmd" != "/usage" ] && [ "$command" != "/usage" ]; then
  printf 'unexpected command: %s\n' "$command"
  exit 3
fi

printf 'Auto (Antigravity) Stats For Nerds\n'
printf '0%% used (Limit resets in 24h)\n'
printf 'Usage limit: 200\n'
printf 'Usage limits span all sessions and reset daily.\n'

IFS= read -r model_command
model_cmd="${model_command#?}"
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
  printf 'unexpected command: %s\n' "$model_command"
  exit 3
fi
printf 'Select Model\n'
printf 'Model usage\n'
printf 'Flash ▬▬▬ 0%%   Resets: 2:15 PM (24h)\n'
printf 'Pro ▬▬▬ 2%%   Resets: 2:15 PM (24h)\n'
printf '(Press Esc to close)\n'

IFS= read -r exit_command
pkill -P $$ 2>/dev/null || true
exit 0
`

	if err := os.WriteFile(fakeAgy, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	checker := NewAntigravityChecker(fakeAgy)
	status, err := checker.Check(ctx)
	if err != nil {
		t.Fatalf("Check failed: %v", err)
	}
	if status.DailyLimit != "100%" {
		t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
	}
	if status.DailyResetTime != "24h" {
		t.Errorf("DailyResetTime: got %q want %q", status.DailyResetTime, "24h")
	}
	if status.Metadata["usage_limit"] != "200" {
		t.Errorf("usage_limit: got %q want %q", status.Metadata["usage_limit"], "200")
	}
	if status.Metadata["used_percent"] != "0%" {
		t.Errorf("used_percent: got %q want %q", status.Metadata["used_percent"], "0%")
	}
	if status.Metadata["daily_label"] != "Daily quota" {
		t.Errorf("daily_label: got %q want %q", status.Metadata["daily_label"], "Daily quota")
	}
	if status.Metadata["model_usage_count"] != "2" {
		t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "2")
	}
	if status.Metadata["model_usage_0_name"] != "Flash" {
		t.Errorf("model_usage_0_name: got %q want %q", status.Metadata["model_usage_0_name"], "Flash")
	}
	if status.Metadata["model_usage_1_used_percent"] != "2%" {
		t.Errorf("model_usage_1_used_percent: got %q want %q", status.Metadata["model_usage_1_used_percent"], "2%")
	}
}

func TestAntigravityCheckerWaitsForInputReady(t *testing.T) {
	dir := t.TempDir()
	fakeAgy := filepath.Join(dir, "agy")

	// Print the banner and non-input-ready workspace line first, then watch
	// stdin for 0.5s. If anything is received before the prompt is rendered,
	// exit 4. Only after the gap do we print the prompt and accept the real
	// /usage command.
	script := `#!/usr/bin/env bash
printf 'Antigravity CLI v0.42.0\n'
printf 'Tips for getting started\n'
printf 'workspace (/directory)\n'
if IFS= read -r -t 0.5 early; then
  printf 'early input before prompt: %s\n' "$early"
  exit 4
fi
printf '? for shortcuts\n'

IFS= read -r command
cmd="${command#?}"
if [ "$cmd" != "/usage" ] && [ "$command" != "/usage" ]; then
  printf 'unexpected command: %s\n' "$command"
  exit 3
fi

printf 'Auto (Antigravity) Stats For Nerds\n'
printf '0%% used (Limit resets in 24h)\n'
printf 'Usage limit: 200\n'

IFS= read -r model_command
model_cmd="${model_command#?}"
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
  printf 'unexpected command: %s\n' "$model_command"
  exit 3
fi
printf 'Select Model\n'
printf 'Model usage\n'
printf 'Flash ▬▬▬ 0%%   Resets: 2:15 PM (24h)\n'
printf '(Press Esc to close)\n'

IFS= read -r exit_command
pkill -P $$ 2>/dev/null || true
exit 0
`

	if err := os.WriteFile(fakeAgy, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()

	checker := NewAntigravityChecker(fakeAgy)
	status, err := checker.Check(ctx)
	if err != nil {
		t.Fatalf("Check failed: %v", err)
	}
	if status.DailyLimit != "100%" {
		t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
	}
	if status.DailyResetTime != "24h" {
		t.Errorf("DailyResetTime: got %q want %q", status.DailyResetTime, "24h")
	}
	if status.Metadata["usage_limit"] != "200" {
		t.Errorf("usage_limit: got %q want %q", status.Metadata["usage_limit"], "200")
	}
	if status.Metadata["model_usage_count"] != "1" {
		t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "1")
	}
}

func TestAntigravityCheckerNoUsageReturnsRawUnparsed(t *testing.T) {
	dir := t.TempDir()
	fakeAgy := filepath.Join(dir, "agy")

	script := `#!/usr/bin/env sh
printf 'Antigravity CLI v0.42.0\n'
printf '? for shortcuts\n'
sleep 0.1

IFS= read -r command
cmd="${command#?}"
if [ "$cmd" != "/usage" ] && [ "$command" != "/usage" ]; then
  printf 'unexpected command: %s\n' "$command"
  exit 3
fi

printf 'Auto (Antigravity) Stats For Nerds\n'
printf 'No API calls have been made in this session.\n'

IFS= read -r model_command
model_cmd="${model_command#?}"
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
  printf 'unexpected command: %s\n' "$model_command"
  exit 3
fi
printf 'Select Model\n'
printf 'Model usage\n'
printf 'Flash ▬▬▬ 0%%   Resets: 2:15 PM (24h)\n'
printf '(Press Esc to close)\n'

IFS= read -r exit_command
pkill -P $$ 2>/dev/null || true
exit 0
`

	if err := os.WriteFile(fakeAgy, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	checker := NewAntigravityChecker(fakeAgy)
	status, err := checker.Check(ctx)
	if err != nil {
		t.Fatalf("Check failed: %v", err)
	}
	if status.DailyLimit != "" {
		t.Errorf("DailyLimit should be empty, got %q", status.DailyLimit)
	}
	if status.WeeklyLimit != "" {
		t.Errorf("WeeklyLimit should be empty, got %q", status.WeeklyLimit)
	}
	if status.RawOutput == "" {
		t.Error("RawOutput should not be empty")
	}
	if status.Metadata["model_usage_count"] != "1" {
		t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "1")
	}
}

func TestAntigravityCheckerParsesScreenReaderQuotaWithNoAPICalls(t *testing.T) {
	dir := t.TempDir()
	fakeAgy := filepath.Join(dir, "agy")

	script := `#!/usr/bin/env sh
printf 'Antigravity CLI v0.42.0\n'
printf 'workspace (/directory)\n'
printf 'Auto (Antigravity) quota\n'
printf '0%% used\n'
printf '? for shortcuts\n'
sleep 0.1

IFS= read -r command
cmd="${command#?}"
if [ "$cmd" != "/usage" ] && [ "$command" != "/usage" ]; then
  printf 'unexpected command: %s\n' "$command"
  exit 3
fi

printf 'No API calls have been made in this session.\n'

IFS= read -r model_command
model_cmd="${model_command#?}"
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
  printf 'unexpected command: %s\n' "$model_command"
  exit 3
fi
printf 'Select Model\n'
printf 'Model usage\n'
printf 'Flash ▬▬▬ 0%%   Resets: 2:15 PM (24h)\n'
printf '(Press Esc to close)\n'

IFS= read -r exit_command
pkill -P $$ 2>/dev/null || true
exit 0
`

	if err := os.WriteFile(fakeAgy, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	checker := NewAntigravityChecker(fakeAgy)
	status, err := checker.Check(ctx)
	if err != nil {
		t.Fatalf("Check failed: %v", err)
	}
	if status.DailyLimit != "100%" {
		t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
	}
	if status.DailyResetTime != "" {
		t.Errorf("DailyResetTime should be empty, got %q", status.DailyResetTime)
	}
	if status.Metadata["used_percent"] != "0%" {
		t.Errorf("used_percent: got %q want %q", status.Metadata["used_percent"], "0%")
	}
	if status.Metadata["usage_limit"] != "" {
		t.Errorf("usage_limit should be empty, got %q", status.Metadata["usage_limit"])
	}
	if status.Metadata["model_usage_count"] != "1" {
		t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "1")
	}
}

func TestAntigravityCheckerParsesScreenReaderQuotaWithoutLimit(t *testing.T) {
	dir := t.TempDir()
	fakeAgy := filepath.Join(dir, "agy")

	script := `#!/usr/bin/env sh
printf 'Antigravity CLI v0.42.0\n'
printf '? for shortcuts\n'
sleep 0.1

IFS= read -r command
cmd="${command#?}"
if [ "$cmd" != "/usage" ] && [ "$command" != "/usage" ]; then
  printf 'unexpected command: %s\n' "$command"
  exit 3
fi

printf 'Auto (Antigravity) Stats For Nerds\n'
printf '0%% used (Limit resets in 24h)\n'
printf 'Usage limits span all sessions.\n'

IFS= read -r model_command
model_cmd="${model_command#?}"
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
  printf 'unexpected command: %s\n' "$model_command"
  exit 3
fi
printf 'Select Model\n'
printf 'Model usage\n'
printf 'Flash ▬▬▬ 0%%   Resets: 2:15 PM (24h)\n'
printf '(Press Esc to close)\n'

IFS= read -r exit_command
pkill -P $$ 2>/dev/null || true
exit 0
`

	if err := os.WriteFile(fakeAgy, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	checker := NewAntigravityChecker(fakeAgy)
	status, err := checker.Check(ctx)
	if err != nil {
		t.Fatalf("Check failed: %v", err)
	}
	if status.DailyLimit != "100%" {
		t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
	}
	if status.DailyResetTime != "24h" {
		t.Errorf("DailyResetTime: got %q want %q", status.DailyResetTime, "24h")
	}
	if status.Metadata["used_percent"] != "0%" {
		t.Errorf("used_percent: got %q want %q", status.Metadata["used_percent"], "0%")
	}
	if status.Metadata["usage_limit"] != "" {
		t.Errorf("usage_limit should be empty, got %q", status.Metadata["usage_limit"])
	}
}

func TestAntigravityCheckerModelUsageOptionalFallback(t *testing.T) {
	dir := t.TempDir()
	fakeAgy := filepath.Join(dir, "agy")

	script := `#!/usr/bin/env sh
printf 'Antigravity CLI v0.42.0\n'
printf '? for shortcuts\n'
sleep 0.1

IFS= read -r command
cmd="${command#?}"
if [ "$cmd" != "/usage" ] && [ "$command" != "/usage" ]; then
  printf 'unexpected command: %s\n' "$command"
  exit 3
fi

printf 'Auto (Antigravity) Stats For Nerds\n'
printf '0%% used (Limit resets in 24h)\n'
printf 'Usage limit: 200\n'

IFS= read -r model_command
exit 1
`

	if err := os.WriteFile(fakeAgy, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	checker := NewAntigravityChecker(fakeAgy)
	status, err := checker.Check(ctx)
	if err != nil {
		t.Fatalf("Check failed despite optional /model fallback: %v", err)
	}
	if status.DailyLimit != "100%" {
		t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
	}
	if status.Metadata["usage_limit"] != "200" {
		t.Errorf("usage_limit: got %q want %q", status.Metadata["usage_limit"], "200")
	}
	if status.Metadata["used_percent"] != "0%" {
		t.Errorf("used_percent: got %q want %q", status.Metadata["used_percent"], "0%")
	}
	if status.Metadata["model_usage_count"] != "" {
		t.Errorf("model_usage_count should be empty, got %q", status.Metadata["model_usage_count"])
	}
}

func TestAntigravityCheckerReadyRegexScope(t *testing.T) {
	dir := t.TempDir()
	fakeAgy := filepath.Join(dir, "agy")

	script := `#!/usr/bin/env bash
printf 'Antigravity CLI v0.42.0\n'
printf 'Auto (Antigravity) quota\n'
printf '0%% used\n'
printf '? for shortcuts\n'
sleep 0.1

IFS= read -r command
cmd="${command#?}"
if [ "$cmd" != "/usage" ] && [ "$command" != "/usage" ]; then
  printf 'unexpected command: %s\n' "$command"
  exit 3
fi

# Check for early /model command within 0.5s before /usage response is outputted
if IFS= read -r -t 0.5 early_command; then
  printf 'early model command received before /usage response: %s\n' "$early_command"
  exit 5
fi

# Send the actual /usage response since no early command arrived
printf 'Usage limit: 200\n'
printf '0%% used (Limit resets in 24h)\n'

# Now read the normal /model command
IFS= read -r model_command
model_cmd="${model_command#?}"
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
  printf 'unexpected command: %s\n' "$model_command"
  exit 3
fi
printf 'Select Model\n'
printf 'Model usage\n'
printf 'Flash ▬▬▬ 0%%   Resets: 2:15 PM (24h)\n'
printf '(Press Esc to close)\n'

IFS= read -r exit_command
pkill -P $$ 2>/dev/null || true
exit 0
`

	if err := os.WriteFile(fakeAgy, []byte(script), 0o755); err != nil {
		t.Fatalf("write fake agy: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	checker := NewAntigravityChecker(fakeAgy)
	status, err := checker.Check(ctx)
	if err != nil {
		t.Fatalf("Check failed: %v", err)
	}
	if status.DailyLimit != "100%" {
		t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
	}
	if status.DailyResetTime != "24h" {
		t.Errorf("DailyResetTime: got %q want %q", status.DailyResetTime, "24h")
	}
	if status.Metadata["usage_limit"] != "200" {
		t.Errorf("usage_limit: got %q want %q", status.Metadata["usage_limit"], "200")
	}
	if status.Metadata["used_percent"] != "0%" {
		t.Errorf("used_percent: got %q want %q", status.Metadata["used_percent"], "0%")
	}
	if status.Metadata["model_usage_count"] != "1" {
		t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "1")
	}
}
