package commerce

import (
	"context"
	"fmt"
	"io"
	"mime"
	"os"
	"path/filepath"
	"strings"
	"time"
)

const brandLogoMaxBytes = 2 << 20
const brandAssetMaxBytes = 30 << 20

var defaultHeroSlides = []map[string]any{
	{"nav_title": "香港 CN2 特惠", "kicker": "云端特惠", "title": "香港 CN2 云服务", "description": "稳定性能与快速交付，满足业务上云需求。", "action": "立即查看", "href": "/activities", "background": "/theme-home/hero-cn2.png"},
	{"nav_title": "云服务限时优惠", "kicker": "云端钜惠", "title": "云服务限时优惠", "description": "精选云计算资源，稳定性能与快速交付一步到位。", "action": "查看活动", "href": "/store", "background": "/hero-new-user.jpeg"},
	{"nav_title": "全球云服务", "kicker": "全球节点", "title": "全球云服务年付特惠", "description": "优质节点与精品网络组合交付。", "action": "立即选购", "href": "/store", "background": "/theme-home/hero-cloud.jpeg"},
}

func (s *Service) SiteBranding(ctx context.Context) (map[string]any, error) {
	brand := map[string]any{"site_name": "网站", "logo_url": ""}
	if s.db == nil {
		return brand, nil
	}
	brand["hero_video_url"], brand["hero_title"], brand["hero_description"], brand["hero_slides"] = "", "", "", defaultHeroSlides
	brand["auth_background_type"], brand["auth_background_url"] = "video", "/bg.mp4"
	var settings []SystemSetting
	keys := []string{
		"platform.site_name", "platform.logo_url",
		"frontend.hero_video_url", "frontend.hero_title", "frontend.hero_description",
		"frontend.hero_slides", "frontend.auth_background_type", "frontend.auth_background_url",
	}
	if err := s.db.WithContext(ctx).Where("`key` IN ?", keys).Find(&settings).Error; err != nil {
		return nil, err
	}
	for _, item := range settings {
		value := strings.TrimSpace(settingStringCommerce(item.Value, ""))
		if item.Key == "platform.site_name" && value != "" {
			brand["site_name"] = value
		}
		if item.Key == "platform.logo_url" && value != "" {
			brand["logo_url"] = value + "?v=" + fmt.Sprint(item.UpdatedAt.Unix())
		}
		if item.Key == "frontend.hero_video_url" {
			brand["hero_video_url"] = value
		}
		if item.Key == "frontend.hero_title" {
			brand["hero_title"] = value
		}
		if item.Key == "frontend.hero_description" {
			brand["hero_description"] = value
		}
		if item.Key == "frontend.hero_slides" {
			if slides, ok := jsonAnyValue(item.Value).([]any); ok && len(slides) > 0 {
				brand["hero_slides"] = slides
			}
		}
		if item.Key == "frontend.auth_background_type" && (value == "image" || value == "video") {
			brand["auth_background_type"] = value
		}
		if item.Key == "frontend.auth_background_url" && value != "" {
			brand["auth_background_url"] = value
		}
	}
	return brand, nil
}

func (s *Service) AdminUpdateFrontendConfig(ctx context.Context, values map[string]any) (map[string]any, error) {
	allowed := map[string]bool{
		"platform.site_name":            true,
		"frontend.hero_video_url":       true,
		"frontend.hero_title":           true,
		"frontend.hero_description":     true,
		"frontend.hero_slides":          true,
		"frontend.auth_background_type": true,
		"frontend.auth_background_url":  true,
	}
	for key, value := range values {
		if !allowed[key] {
			return nil, BadRequest("不支持的前端配置项")
		}
		if _, err := s.AdminSetSetting(ctx, key, AdminSettingRequest{Value: value}); err != nil {
			return nil, err
		}
	}
	return s.SiteBranding(ctx)
}

func (s *Service) AdminFrontendConfig(ctx context.Context) (map[string]any, error) {
	if s.db != nil {
		var count int64
		_ = s.db.WithContext(ctx).Model(&SystemSetting{}).Where("`key` = ?", "frontend.hero_slides").Count(&count).Error
		if count == 0 {
			_, _ = s.AdminSetSetting(ctx, "frontend.hero_slides", AdminSettingRequest{Value: defaultHeroSlides})
		}
	}
	return s.SiteBranding(ctx)
}

func (s *Service) UploadBrandLogo(ctx context.Context, file io.Reader, filename, contentType string) (map[string]any, error) {
	if err := s.requireDB(); err != nil {
		return nil, err
	}
	raw, err := io.ReadAll(io.LimitReader(file, brandLogoMaxBytes+1))
	if err != nil {
		return nil, err
	}
	if len(raw) == 0 || len(raw) > brandLogoMaxBytes {
		return nil, BadRequest("Logo 文件需小于 2MB")
	}
	ext := map[string]string{"image/png": ".png", "image/jpeg": ".jpg", "image/webp": ".webp", "image/svg+xml": ".svg"}[strings.ToLower(strings.TrimSpace(contentType))]
	if ext == "" {
		ext = strings.ToLower(filepath.Ext(filename))
	}
	if ext != ".png" && ext != ".jpg" && ext != ".jpeg" && ext != ".webp" && ext != ".svg" {
		return nil, BadRequest("仅支持 PNG、JPG、WebP 或 SVG 格式")
	}
	if ext == ".jpeg" {
		ext = ".jpg"
	}
	dir := filepath.Join("data", "branding")
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return nil, err
	}
	path := filepath.Join(dir, "logo"+ext)
	if err := os.WriteFile(path, raw, 0o644); err != nil {
		return nil, err
	}
	if _, err := s.AdminSetSetting(ctx, "platform.logo_url", AdminSettingRequest{Value: "/api/v1/site-branding/logo"}); err != nil {
		return nil, err
	}
	return s.SiteBranding(ctx)
}

func (s *Service) UploadBrandAsset(ctx context.Context, file io.Reader, filename, contentType string) (map[string]any, error) {
	if err := s.requireDB(); err != nil {
		return nil, err
	}
	raw, err := io.ReadAll(io.LimitReader(file, brandAssetMaxBytes+1))
	if err != nil {
		return nil, err
	}
	if len(raw) == 0 || len(raw) > brandAssetMaxBytes {
		return nil, BadRequest("资源文件需小于 30MB")
	}

	ext := strings.ToLower(filepath.Ext(filename))
	if ext == "" {
		ext = map[string]string{
			"image/png": ".png", "image/jpeg": ".jpg", "image/webp": ".webp",
			"video/mp4": ".mp4", "video/webm": ".webm",
		}[strings.ToLower(contentType)]
	}
	allowed := map[string]bool{".png": true, ".jpg": true, ".jpeg": true, ".webp": true, ".mp4": true, ".webm": true}
	if !allowed[ext] {
		return nil, BadRequest("仅支持 PNG、JPG、WebP、MP4 或 WebM")
	}

	dir := filepath.Join("data", "branding", "assets")
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return nil, err
	}
	name := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext)
	if err := os.WriteFile(filepath.Join(dir, name), raw, 0o644); err != nil {
		return nil, err
	}
	return map[string]any{
		"url":  "/api/v1/site-branding/assets/" + name,
		"kind": strings.TrimPrefix(ext, "."),
	}, nil
}

func (s *Service) BrandLogoFile(ctx context.Context) (string, string, error) {
	if s.db == nil {
		return "", "", NotFound("未配置站点 Logo")
	}
	var item SystemSetting
	if err := s.db.WithContext(ctx).Where("`key` = ?", "platform.logo_url").First(&item).Error; err != nil {
		return "", "", err
	}
	for _, ext := range []string{".png", ".jpg", ".webp", ".svg"} {
		path := filepath.Join("data", "branding", "logo"+ext)
		if _, err := os.Stat(path); err == nil {
			return path, mime.TypeByExtension(ext), nil
		}
	}
	return "", "", NotFound("Logo 文件不存在")
}

func (s *Service) BrandAssetFile(name string) (string, string, error) {
	name = filepath.Base(name)
	if name == "." || name == "" {
		return "", "", BadRequest("无效资源")
	}
	path := filepath.Join("data", "branding", "assets", name)
	if _, err := os.Stat(path); err != nil {
		return "", "", NotFound("资源不存在")
	}
	return path, mime.TypeByExtension(filepath.Ext(name)), nil
}
