package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"time"
)

const bingAPIBase = "https://www.bing.com/HPImageArchive.aspx?format=js&n=8&mkt=zh-CN"

type bingResponse struct {
	Images []struct {
		StartDate string `json:"startdate"`
		URL       string `json:"url"`
		URLBase   string `json:"urlbase"`
		Copyright string `json:"copyright"`
	} `json:"images"`
}

type BingRecord struct {
	Date      string `json:"date"`
	URLBase   string `json:"urlbase"`
	Copyright string `json:"copyright"`
	Filename  string `json:"filename"`
	Favorited bool   `json:"favorited"`
}

type BingHistory struct {
	Records    []BingRecord `json:"records"`
	CurrentIdx int          `json:"currentIdx"`
}

var bingMu sync.Mutex

func bingDir() string {
	return filepath.Join(configDir(), "bing")
}

func bingHistoryPath() string {
	return filepath.Join(configDir(), "bing_history.json")
}

func loadBingHistory() *BingHistory {
	data, err := os.ReadFile(bingHistoryPath())
	if err != nil {
		return &BingHistory{}
	}
	var h BingHistory
	if json.Unmarshal(data, &h) != nil {
		return &BingHistory{}
	}
	return &h
}

func saveBingHistory(h *BingHistory) error {
	data, _ := json.MarshalIndent(h, "", "  ")
	return os.WriteFile(bingHistoryPath(), data, 0644)
}

func fetchBingHistory() {
	bingMu.Lock()
	defer bingMu.Unlock()

	os.MkdirAll(bingDir(), 0755)
	existing := loadBingHistory()
	existingMap := make(map[string]BingRecord)
	for _, r := range existing.Records {
		existingMap[r.Date] = r
	}

	// 分页下载: idx=0,8,16... 直到命中已有记录或无新图片
	for idx := 0; idx < 80; idx += 8 {
		url := fmt.Sprintf("%s&idx=%d", bingAPIBase, idx)
		resp, err := httpClient.Get(url)
		if err != nil {
			log.Printf("Bing API 请求失败 (idx=%d): %v", idx, err)
			break
		}
		data, _ := io.ReadAll(resp.Body)
		resp.Body.Close()
		var br bingResponse
		if json.Unmarshal(data, &br) != nil || len(br.Images) == 0 {
			break
		}

		newCount := 0
		for _, img := range br.Images {
			date := img.StartDate
			if date == "" {
				continue
			}
			if _, exists := existingMap[date]; exists {
				continue
			}

			imgURL := img.URL
			if !strings.HasPrefix(imgURL, "http") {
				imgURL = "https://www.bing.com" + imgURL
			}

			imgResp, err := httpClient.Get(imgURL)
			if err != nil {
				continue
			}
			imgData, _ := io.ReadAll(imgResp.Body)
			imgResp.Body.Close()
			if len(imgData) == 0 {
				continue
			}

			filename := date + ".jpg"
			localPath := filepath.Join(bingDir(), filename)
			os.WriteFile(localPath, imgData, 0644)
			log.Printf("Bing 壁纸已下载: %s (%d bytes)", filename, len(imgData))

			existingMap[date] = BingRecord{
				Date:      date,
				URLBase:   img.URLBase,
				Copyright: img.Copyright,
				Filename:  filename,
			}
			newCount++
		}

		if newCount == 0 && idx > 0 {
			break
		}
		time.Sleep(500 * time.Millisecond)
	}

	// 按 API 返回顺序重建 records (newest first)
	// 用 existingMap 里所有记录按 date 降序排列
	var records []BingRecord
	for _, r := range existingMap {
		records = append(records, r)
	}
	sort.Slice(records, func(i, j int) bool {
		return records[i].Date > records[j].Date
	})

	history := &BingHistory{
		Records:    records,
		CurrentIdx: 0,
	}
	if existing.CurrentIdx < len(records) {
		history.CurrentIdx = existing.CurrentIdx
	}
	saveBingHistory(history)

	log.Printf("Bing 壁纸: 共 %d 张", len(records))
	reloadWallpaper()
}

func getCurrentBingPath() string {
	h := loadBingHistory()
	if h.CurrentIdx < 0 || h.CurrentIdx >= len(h.Records) {
		return ""
	}
	return filepath.Join(bingDir(), h.Records[h.CurrentIdx].Filename)
}

func getCurrentBingRecord() *BingRecord {
	h := loadBingHistory()
	if h.CurrentIdx < 0 || h.CurrentIdx >= len(h.Records) {
		return nil
	}
	return &h.Records[h.CurrentIdx]
}

func bingPrev() {
	bingMu.Lock()
	defer bingMu.Unlock()

	h := loadBingHistory()
	if len(h.Records) == 0 {
		return
	}
	h.CurrentIdx = (h.CurrentIdx + 1) % len(h.Records)
	saveBingHistory(h)
	log.Printf("Bing 壁纸: 上一个 (idx=%d, date=%s)", h.CurrentIdx, h.Records[h.CurrentIdx].Date)
	bingReloadImage()
}

func bingNext() {
	bingMu.Lock()
	defer bingMu.Unlock()

	h := loadBingHistory()
	if len(h.Records) == 0 {
		return
	}
	h.CurrentIdx = (h.CurrentIdx - 1 + len(h.Records)) % len(h.Records)
	saveBingHistory(h)
	log.Printf("Bing 壁纸: 下一个 (idx=%d, date=%s)", h.CurrentIdx, h.Records[h.CurrentIdx].Date)
	bingReloadImage()
}

func bingToggleFavorite() string {
	bingMu.Lock()
	defer bingMu.Unlock()

	h := loadBingHistory()
	if h.CurrentIdx < 0 || h.CurrentIdx >= len(h.Records) {
		return ""
	}
	r := &h.Records[h.CurrentIdx]
	r.Favorited = !r.Favorited
	saveBingHistory(h)
	if r.Favorited {
		log.Printf("Bing 壁纸: 已收藏 (date=%s)", r.Date)
		return "☆ 取消收藏"
	}
	log.Printf("Bing 壁纸: 已取消收藏 (date=%s)", r.Date)
	return "★ 收藏当前壁纸"
}

func bingCurrentState() string {
	h := loadBingHistory()
	if h.CurrentIdx < 0 || h.CurrentIdx >= len(h.Records) {
		return `{"fav":false,"label":"☆","copyright":"","idx":0,"total":0}`
	}
	r := h.Records[h.CurrentIdx]
	label := "☆"
	if r.Favorited {
		label = "⭐"
	}
	data, _ := json.Marshal(map[string]interface{}{
		"fav":       r.Favorited,
		"label":     label,
		"copyright": r.Copyright,
		"date":      r.Date,
		"filename":  r.Filename,
		"idx":       h.CurrentIdx,
		"total":     len(h.Records),
	})
	return string(data)
}

func bingFavoritesJSON() string {
	h := loadBingHistory()
	type favItem struct {
		Date      string `json:"date"`
		Copyright string `json:"copyright"`
		Filename  string `json:"filename"`
		Idx       int    `json:"idx"`
	}
	var favs []favItem
	for i, r := range h.Records {
		if r.Favorited {
			favs = append(favs, favItem{r.Date, r.Copyright, r.Filename, i})
		}
	}
	if favs == nil {
		favs = []favItem{}
	}
	data, _ := json.Marshal(favs)
	return string(data)
}

func bingSetByIdx(idx int) string {
	bingMu.Lock()
	defer bingMu.Unlock()
	h := loadBingHistory()
	if idx < 0 || idx >= len(h.Records) {
		return bingCurrentState()
	}
	h.CurrentIdx = idx
	saveBingHistory(h)
	bingReloadImage()
	return bingCurrentState()
}

func bingThumbDataURI(filename string) string {
	p := filepath.Join(bingDir(), filename)
	return imageToDataURI(p)
}

func bingWallpaperLoop() {
	cfg := loadConfig()
	if cfg.WallpaperType == WPBing {
		h := loadBingHistory()
		if len(h.Records) == 0 {
			fetchBingHistory()
		} else {
			reloadWallpaper()
		}
	}

	// 定时切换壁纸 (1 小时间隔)
	go func() {
		ticker := time.NewTicker(1 * time.Hour)
		for range ticker.C {
			cfg := loadConfig()
			if cfg.WallpaperType != WPBing || !cfg.BingAutoRefresh {
				continue
			}
			bingMu.Lock()
			h := loadBingHistory()
			if len(h.Records) <= 1 {
				bingMu.Unlock()
				continue
			}
			h.CurrentIdx = (h.CurrentIdx + 1) % len(h.Records)
			saveBingHistory(h)
			bingMu.Unlock()
			bingReloadImage()
			log.Printf("Bing 自动切换: idx=%d/%d", h.CurrentIdx, len(h.Records))
		}
	}()

	go func() {
		fetchTicker := time.NewTicker(4 * time.Hour)
		for range fetchTicker.C {
			cfg := loadConfig()
			if cfg.WallpaperType == WPBing {
				go fetchBingHistory()
			}
		}
	}()
}
