package openapi_test

import (
	"context"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/unkn0wn-root/resterm/internal/openapi"
	"github.com/unkn0wn-root/resterm/internal/openapi/generator"
	"github.com/unkn0wn-root/resterm/internal/openapi/parser"
	"github.com/unkn0wn-root/resterm/internal/openapi/writer"
)

func TestServiceGenerateHTTPFile(t *testing.T) {
	t.Parallel()

	svc := &openapi.Service{
		Parser:    parser.NewLoader(),
		Generator: generator.NewBuilder(),
		Writer:    writer.NewFileWriter(),
	}
	specPath := filepath.Join("testdata", "deviceinventory.yaml")
	dest := filepath.Join(t.TempDir(), "generated.http")

	opts := openapi.GenerateOptions{
		Write: openapi.WriterOptions{
			HeaderComment:     "Generated by resterm tests",
			OverwriteExisting: true,
		},
	}

	if err := svc.GenerateHTTPFile(context.Background(), specPath, dest, opts); err != nil {
		t.Fatalf("GenerateHTTPFile: %v", err)
	}

	got, err := os.ReadFile(dest)
	if err != nil {
		t.Fatalf("read generated file: %v", err)
	}

	goldenPath := filepath.Join("writer", "testdata", "deviceinventory.http")
	want, err := os.ReadFile(goldenPath)
	if err != nil {
		t.Fatalf("read golden file: %v", err)
	}

	if strings.TrimSpace(string(got)) != strings.TrimSpace(string(want)) {
		t.Fatalf("generated file mismatch\nGot:\n%s\nWant:\n%s", string(got), string(want))
	}

	// second run without overwrite should fail
	opts.Write.OverwriteExisting = false
	if err := svc.GenerateHTTPFile(context.Background(), specPath, dest, opts); err == nil {
		t.Fatalf("expected overwrite error")
	}
}

func TestServiceGenerateHTTPFileMissingSpec(t *testing.T) {
	t.Parallel()

	svc := &openapi.Service{
		Parser:    parser.NewLoader(),
		Generator: generator.NewBuilder(),
		Writer:    writer.NewFileWriter(),
	}
	dest := filepath.Join(t.TempDir(), "out.http")
	if err := svc.GenerateHTTPFile(
		context.Background(),
		"missing.yaml",
		dest,
		openapi.GenerateOptions{},
	); err == nil {
		t.Fatalf("expected missing spec error")
	}
}

func TestServiceGenerateHTTPFileIncludesParserWarnings(t *testing.T) {
	t.Parallel()

	spec := `openapi: 3.0.3
info:
  title: Header Compat
  version: 1.0.0
paths:
  /demo:
    get:
      responses:
        '200':
          description: ok
          headers:
            credential:
              $ref: '#/components/parameters/credential'
components:
  parameters:
    credential:
      name: credential
      in: header
      required: true
      schema:
        type: string
`
	dir := t.TempDir()
	specPath := filepath.Join(dir, "spec.yaml")
	if err := os.WriteFile(specPath, []byte(spec), 0o644); err != nil {
		t.Fatalf("write spec: %v", err)
	}

	svc := &openapi.Service{
		Parser:    parser.NewLoader(),
		Generator: generator.NewBuilder(),
		Writer:    writer.NewFileWriter(),
	}
	dest := filepath.Join(dir, "generated.http")
	opts := openapi.GenerateOptions{
		Write: openapi.WriterOptions{
			HeaderComment:     "Generated by resterm tests",
			OverwriteExisting: true,
		},
	}

	if err := svc.GenerateHTTPFile(context.Background(), specPath, dest, opts); err != nil {
		t.Fatalf("GenerateHTTPFile: %v", err)
	}

	got, err := os.ReadFile(dest)
	if err != nil {
		t.Fatalf("read generated file: %v", err)
	}
	txt := string(got)
	if !strings.Contains(
		txt,
		"Warning: OpenAPI compatibility rewrite: converted 1 header $ref occurrence(s)",
	) {
		t.Fatalf("expected parser warning in output header, got:\n%s", txt)
	}
}
