package main

import (
	"context"
	"strings"
	"testing"

	"github.com/shankar0123/certctl/internal/service"
)

// fakeIssuerConn implements service.IssuerConnector enough for preflight tests.
type fakeIssuerConn struct {
	caCertPEM string
	caCertErr error
}

func (f *fakeIssuerConn) IssueCertificate(ctx context.Context, commonName string, sans []string, csrPEM string, ekus []string, maxTTLSeconds int) (*service.IssuanceResult, error) {
	return nil, nil
}
func (f *fakeIssuerConn) RenewCertificate(ctx context.Context, commonName string, sans []string, csrPEM string, ekus []string, maxTTLSeconds int) (*service.IssuanceResult, error) {
	return nil, nil
}
func (f *fakeIssuerConn) RevokeCertificate(ctx context.Context, serial string, reason string) error {
	return nil
}
func (f *fakeIssuerConn) GenerateCRL(ctx context.Context, revokedCerts []service.CRLEntry) ([]byte, error) {
	return nil, nil
}
func (f *fakeIssuerConn) SignOCSPResponse(ctx context.Context, req service.OCSPSignRequest) ([]byte, error) {
	return nil, nil
}
func (f *fakeIssuerConn) GetCACertPEM(ctx context.Context) (string, error) {
	return f.caCertPEM, f.caCertErr
}
func (f *fakeIssuerConn) GetRenewalInfo(ctx context.Context, certPEM string) (*service.RenewalInfoResult, error) {
	return nil, nil
}

// TestPreflightEnrollmentIssuer covers Bundle-4 / L-005 startup validation
// for EST/SCEP issuer binding.
func TestPreflightEnrollmentIssuer(t *testing.T) {
	cases := []struct {
		name        string
		issuer      service.IssuerConnector
		wantErr     bool
		errContains string
	}{
		{
			name:        "nil_connector_fails",
			issuer:      nil,
			wantErr:     true,
			errContains: "connector is nil",
		},
		{
			name: "issuer_returns_error_fails",
			issuer: &fakeIssuerConn{
				caCertErr: errStub("ACME issuers do not provide a static CA certificate"),
			},
			wantErr:     true,
			errContains: "cannot serve CA certificate",
		},
		{
			name: "issuer_returns_empty_pem_fails",
			issuer: &fakeIssuerConn{
				caCertPEM: "",
				caCertErr: nil,
			},
			wantErr:     true,
			errContains: "empty PEM",
		},
		{
			name: "issuer_returns_valid_pem_succeeds",
			issuer: &fakeIssuerConn{
				caCertPEM: "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----",
				caCertErr: nil,
			},
			wantErr: false,
		},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			err := preflightEnrollmentIssuer(context.Background(), "EST", "iss-test", tc.issuer)
			if tc.wantErr && err == nil {
				t.Fatalf("expected error, got nil")
			}
			if !tc.wantErr && err != nil {
				t.Fatalf("unexpected error: %v", err)
			}
			if tc.wantErr && tc.errContains != "" && !strings.Contains(err.Error(), tc.errContains) {
				t.Fatalf("error %q missing substring %q", err.Error(), tc.errContains)
			}
		})
	}
}

// errStub is a tiny error wrapper so test cases can use string literals
// without importing fmt in every test struct entry.
type errStub string

func (e errStub) Error() string { return string(e) }
