package migration

import (
	"bytes"
	"encoding/csv"
	"encoding/json"
	"strings"
	"testing"
)

func TestJobAuditExportCSVFormat(t *testing.T) {
	var buf bytes.Buffer
	cw := csv.NewWriter(&buf)
	if err := cw.Write(jobAuditCSVHeaders); err != nil {
		t.Fatal(err)
	}
	row := JobAuditExportRow{
		ItemID:    "msg-fail",
		RelPath:   "Inbox/foo.eml",
		Status:    ItemStatusFailed,
		Error:     "upload timeout",
		Service:   "mail",
		Timestamp: "2026-06-13T12:00:00Z",
	}
	if err := writeJobAuditCSVRow(cw, row); err != nil {
		t.Fatal(err)
	}
	cw.Flush()
	if err := cw.Error(); err != nil {
		t.Fatal(err)
	}

	reader := csv.NewReader(strings.NewReader(buf.String()))
	records, err := reader.ReadAll()
	if err != nil {
		t.Fatal(err)
	}
	if len(records) != 2 {
		t.Fatalf("records = %d, want 2", len(records))
	}
	if got := strings.Join(records[0], ","); got != "item_id,rel_path,status,error,service,timestamp" {
		t.Fatalf("headers = %q", got)
	}
	if records[1][0] != "msg-fail" || records[1][2] != ItemStatusFailed || records[1][3] != "upload timeout" {
		t.Fatalf("row = %#v", records[1])
	}
}

func TestProjectAuditExportCSVFormat(t *testing.T) {
	var buf bytes.Buffer
	cw := csv.NewWriter(&buf)
	if err := cw.Write(projectAuditCSVHeaders); err != nil {
		t.Fatal(err)
	}
	if err := writeProjectAuditCSVRow(cw, JobAuditExportRow{
		JobID:     "job-1",
		ItemID:    "file-1",
		Status:    ItemStatusImported,
		Service:   "drive",
		Timestamp: "2026-06-13T12:00:00Z",
	}); err != nil {
		t.Fatal(err)
	}
	cw.Flush()

	reader := csv.NewReader(strings.NewReader(buf.String()))
	records, err := reader.ReadAll()
	if err != nil {
		t.Fatal(err)
	}
	if records[0][0] != "job_id" || records[1][0] != "job-1" {
		t.Fatalf("records = %#v", records)
	}
}

func TestJobAuditExportNDJSONFormat(t *testing.T) {
	var buf bytes.Buffer
	enc := json.NewEncoder(&buf)
	if err := enc.Encode(JobAuditExportRow{
		ItemID:    "msg-skip",
		Status:    ItemStatusSkipped,
		Error:     "file too large",
		Service:   "mail",
		Timestamp: "2026-06-13T12:00:00Z",
	}); err != nil {
		t.Fatal(err)
	}

	line := strings.TrimSpace(buf.String())
	var decoded JobAuditExportRow
	if err := json.Unmarshal([]byte(line), &decoded); err != nil {
		t.Fatal(err)
	}
	if decoded.ItemID != "msg-skip" || decoded.Status != ItemStatusSkipped || decoded.Error != "file too large" {
		t.Fatalf("decoded = %#v", decoded)
	}
}

func TestJobAuditExportMeta(t *testing.T) {
	csvMeta := jobAuditExportMeta("csv", "01234567-abcd-efgh", false)
	if csvMeta.ContentType != "text/csv; charset=utf-8" {
		t.Fatalf("csv content type = %q", csvMeta.ContentType)
	}
	if !strings.HasSuffix(csvMeta.FileName, ".csv") {
		t.Fatalf("csv filename = %q", csvMeta.FileName)
	}

	ndMeta := jobAuditExportMeta("ndjson", "01234567-abcd-efgh", true)
	if ndMeta.ContentType != "application/x-ndjson; charset=utf-8" {
		t.Fatalf("ndjson content type = %q", ndMeta.ContentType)
	}
	if !strings.HasPrefix(ndMeta.FileName, "migration-project-audit-") {
		t.Fatalf("project filename = %q", ndMeta.FileName)
	}
}
