package orgpolicy

import (
	"context"
	"encoding/json"
	"os"
	"strings"

	"github.com/jackc/pgx/v5"

	"github.com/ultisuite/ulti-backend/internal/config"
)

// PublicDrivePolicy is exposed to authenticated users (no secrets).
type PublicDrivePolicy struct {
	ConfiguredMountOAuthProviders []string `json:"configured_mount_oauth_providers"`
	MountOAuthRedirectURI         string   `json:"mount_oauth_redirect_uri"`
}

type MountOAuthCredentials struct {
	Enabled      bool
	ClientID     string
	ClientSecret string
}

const (
	MountOAuthProviderGoogle    = "google"
	MountOAuthProviderDropbox   = "dropbox"
	MountOAuthProviderMicrosoft = "microsoft"
)

func defaultMountOAuthSection() map[string]any {
	return DefaultMountOAuthSection()
}

// DefaultMountOAuthSection is the default mount OAuth admin policy shape.
func DefaultMountOAuthSection() map[string]any {
	return map[string]any{
		"redirect_uri": "",
		"google": map[string]any{
			"enabled":       false,
			"client_id":     "",
			"client_secret": "",
		},
		"dropbox": map[string]any{
			"enabled":       false,
			"client_id":     "",
			"client_secret": "",
		},
		"microsoft": map[string]any{
			"enabled":       false,
			"client_id":     "",
			"client_secret": "",
		},
	}
}

func (l *Loader) PublicDrivePolicy(ctx context.Context) (PublicDrivePolicy, error) {
	mountOAuth, err := l.loadMountOAuthSection(ctx)
	if err != nil {
		return PublicDrivePolicy{}, err
	}
	configured := make([]string, 0, 3)
	for _, provider := range []string{MountOAuthProviderGoogle, MountOAuthProviderDropbox, MountOAuthProviderMicrosoft} {
		if creds := parseMountOAuthProvider(mountOAuth, provider); creds.Enabled {
			configured = append(configured, provider)
		}
	}
	return PublicDrivePolicy{
		ConfiguredMountOAuthProviders: configured,
		MountOAuthRedirectURI:         resolveMountOAuthRedirectURI(mountOAuth, newConfigRef(l.cfg)),
	}, nil
}

func (l *Loader) MountOAuthCredentials(ctx context.Context, provider string) (MountOAuthCredentials, error) {
	mountOAuth, err := l.loadMountOAuthSection(ctx)
	if err != nil {
		return MountOAuthCredentials{}, err
	}
	return parseMountOAuthProvider(mountOAuth, provider), nil
}

func (l *Loader) MountOAuthRedirectURI(ctx context.Context) (string, error) {
	mountOAuth, err := l.loadMountOAuthSection(ctx)
	if err != nil {
		return "", err
	}
	return resolveMountOAuthRedirectURI(mountOAuth, newConfigRef(l.cfg)), nil
}

func (l *Loader) loadMountOAuthSection(ctx context.Context) (map[string]any, error) {
	var raw []byte
	err := l.db.QueryRow(ctx, `
		SELECT settings FROM org_settings WHERE id = $1
	`, orgSettingsSingletonID).Scan(&raw)
	if err != nil && err != pgx.ErrNoRows {
		return nil, err
	}
	stored := map[string]any{}
	if len(raw) > 0 {
		if err := json.Unmarshal(raw, &stored); err != nil {
			return nil, err
		}
	}
	filePolicies, _ := stored["file_policies"].(map[string]any)
	if filePolicies == nil {
		return defaultMountOAuthSection(), nil
	}
	mountOAuth, _ := filePolicies["mount_oauth"].(map[string]any)
	if mountOAuth == nil {
		return defaultMountOAuthSection(), nil
	}
	return mountOAuth, nil
}

func parseMountOAuthProvider(mountOAuth map[string]any, provider string) MountOAuthCredentials {
	section, _ := mountOAuth[provider].(map[string]any)
	if section == nil {
		return MountOAuthCredentials{}
	}
	clientID := strings.TrimSpace(stringValue(section["client_id"]))
	clientSecret := strings.TrimSpace(stringValue(section["client_secret"]))
	enabled := boolValue(section["enabled"])
	if !enabled {
		return MountOAuthCredentials{}
	}
	if clientID == "" || clientSecret == "" {
		return MountOAuthCredentials{}
	}
	return MountOAuthCredentials{
		Enabled:      true,
		ClientID:     clientID,
		ClientSecret: clientSecret,
	}
}

func resolveMountOAuthRedirectURI(mountOAuth map[string]any, cfg *configRef) string {
	if uri := strings.TrimSpace(stringValue(mountOAuth["redirect_uri"])); uri != "" {
		return uri
	}
	if cfg != nil {
		if appURL := strings.TrimSpace(cfg.mailAppURL); appURL != "" {
			return strings.TrimRight(appURL, "/") + "/drive/mounts/oauth/callback"
		}
		if ultidURL := strings.TrimSpace(cfg.ultidPublicURL); ultidURL != "" {
			return strings.TrimRight(ultidURL, "/") + "/drive/mounts/oauth/callback"
		}
	}
	if appURL := strings.TrimSpace(os.Getenv("MAIL_APP_URL")); appURL != "" {
		return strings.TrimRight(appURL, "/") + "/drive/mounts/oauth/callback"
	}
	if appURL := strings.TrimSpace(os.Getenv("NEXT_PUBLIC_APP_URL")); appURL != "" {
		return strings.TrimRight(appURL, "/") + "/drive/mounts/oauth/callback"
	}
	return "http://localhost:3004/drive/mounts/oauth/callback"
}

type configRef struct {
	mailAppURL      string
	ultidPublicURL  string
}

func newConfigRef(cfg *config.Config) *configRef {
	if cfg == nil {
		return nil
	}
	return &configRef{
		mailAppURL:     cfg.MailAppURL,
		ultidPublicURL: cfg.UltidPublicURL,
	}
}
