package main

import (
	"context"
	"flag"
	"log"
	"os"
	"sync"
	"time"
	"weatherstation/internal/config"
	"weatherstation/internal/database"
	"weatherstation/internal/forecast"
	"weatherstation/internal/radar"
	"weatherstation/internal/rain"
	"weatherstation/internal/selftest"
	"weatherstation/internal/server"
	"weatherstation/internal/tools"
)

func main() {
	// 命令行参数
	var webOnly = flag.Bool("web", false, "只启动Web服务器（Gin）")
	var udpOnly = flag.Bool("udp", false, "只启动UDP服务器")
	// 调试：回填10分钟表
	var doBackfill = flag.Bool("backfill", false, "将16s原始数据聚合写入10分钟表（调试用途）")
	var bfStation = flag.String("station", "", "指定站点ID（为空则全站回填）")
	var bfFrom = flag.String("from", "", "回填起始时间，格式：YYYY-MM-DD HH:MM:SS")
	var bfTo = flag.String("to", "", "回填结束时间，格式：YYYY-MM-DD HH:MM:SS")
	var bfWrap = flag.Float64("wrap", 0, "回绕一圈对应毫米值（mm），<=0 则降级为仅计当前值")
	// 自检控制
	var noSelftest = flag.Bool("no-selftest", false, "跳过启动自检")
	var selftestOnly = flag.Bool("selftest_only", false, "仅执行自检后退出")
	// 预报抓取
	var forecastOnly = flag.Bool("forecast_only", false, "仅执行一次open-meteo拉取并退出")
	var caiyunOnly = flag.Bool("caiyun_only", false, "仅执行一次彩云拉取并退出")
	var cmaCLI = flag.Bool("cma_cli", false, "仅执行一次CMA接口抓取并打印未来三小时")
	var cmaOnly = flag.Bool("cma_only", false, "仅执行一次CMA拉取并退出")
	var forecastDay = flag.String("forecast_day", "", "按日期抓取当天0点到当前时间+3h（格式YYYY-MM-DD）")
	// 历史数据补完
	var historicalOnly = flag.Bool("historical_only", false, "仅执行历史数据补完并退出")
	var historicalStart = flag.String("historical_start", "", "历史数据开始日期（格式YYYY-MM-DD）")
	var historicalEnd = flag.String("historical_end", "", "历史数据结束日期（格式YYYY-MM-DD）")
	// 覆盖风：使用彩云实况替换导出中的风速/风向
	var useWindOverride = flag.Bool("wind", false, "使用彩云实况覆盖导出CSV中的风速/风向")
	// 历史CSV导出
	var exportRangeOnly = flag.Bool("export_range", false, "按日期范围导出10分钟CSV（含ZTD融合），并退出。日期格式支持 YYYY-MM-DD 或 YYYYMMDD")
	var exportStart = flag.String("export_start", "", "导出起始日期（含），格式 YYYY-MM-DD 或 YYYYMMDD")
	var exportEnd = flag.String("export_end", "", "导出结束日期（含），格式 YYYY-MM-DD 或 YYYYMMDD")
	// 雷达：导入单个CMA瓦片到数据库
	var importTile = flag.Bool("import_tile", false, "导入一个CMA雷达瓦片到数据库并退出")
	var tileURL = flag.String("tile_url", "", "瓦片URL或/tiles/...路径，用于解析product/时间/z/y/x")
	var tilePath = flag.String("tile_path", "", "瓦片本地文件路径（.bin）")
	flag.Parse()

	// 设置日志
	server.SetupLogger()

	// 初始化数据库连接
	_ = database.GetDB() // 确保PostgreSQL连接已初始化
	defer database.Close()
	// 初始化MySQL连接（如果配置存在）
	_ = database.GetMySQL()
	defer database.CloseMySQL()

	// 启动前自检
	if !*noSelftest {
		if err := selftest.Run(context.Background()); err != nil {
			log.Fatalf("启动自检失败: %v", err)
		}
		if *selftestOnly {
			log.Println("自检完成，按 --selftest_only 要求退出")
			return
		}
	}

	// 单次 open-meteo 拉取
	if *forecastOnly {
		if err := forecast.RunOpenMeteoFetch(context.Background()); err != nil {
			log.Fatalf("open-meteo 拉取失败: %v", err)
		}
		log.Println("open-meteo 拉取完成")
		return
	}

	// 单次 彩云 拉取（token 从环境变量 CAIYUN_TOKEN 或命令行 -caiyun_token 读取）
	if *caiyunOnly {
		token := os.Getenv("CAIYUN_TOKEN")
		if token == "" {
			// 退回配置
			token = config.GetConfig().Forecast.CaiyunToken
			if token == "" {
				log.Fatalf("未提供彩云 token，请设置环境变量 CAIYUN_TOKEN 或配置文件 forecast.caiyun_token")
			}
		}
		if err := forecast.RunCaiyunFetch(context.Background(), token); err != nil {
			log.Fatalf("caiyun 拉取失败: %v", err)
		}
		log.Println("caiyun 拉取完成")
		return
	}

	// 单次 CMA 拉取（固定参数）写库并退出
	if *cmaOnly {
		if err := forecast.RunCMAFetch(context.Background()); err != nil {
			log.Fatalf("CMA 拉取失败: %v", err)
		}
		log.Println("CMA 拉取完成")
		return
	}

	// 单次 CMA 拉取（固定参数）并打印三小时
	if *cmaCLI {
		if err := forecast.RunCMACLI(context.Background()); err != nil {
			log.Fatalf("CMA 拉取失败: %v", err)
		}
		return
	}

	// 导入一个CMA雷达瓦片到数据库
	if *importTile {
		if *tileURL == "" || *tilePath == "" {
			log.Fatalln("import_tile 需要提供 --tile_url 与 --tile_path")
		}
		if err := radar.ImportTileFile(context.Background(), *tileURL, *tilePath); err != nil {
			log.Fatalf("导入雷达瓦片失败: %v", err)
		}
		log.Println("导入雷达瓦片完成")
		return
	}

	// 历史CSV范围导出
	if *exportRangeOnly {
		if *exportStart == "" || *exportEnd == "" {
			log.Fatalln("export_range 需要提供 --export_start 与 --export_end 日期（YYYY-MM-DD 或 YYYYMMDD）")
		}
		var opts tools.ExporterOptions
		if *useWindOverride {
			token := os.Getenv("CAIYUN_TOKEN")
			if token == "" {
				token = config.GetConfig().Forecast.CaiyunToken
			}
			if token == "" {
				log.Println("警告: 指定了 --wind 但未提供彩云 token，忽略风覆盖")
			} else {
				opts.OverrideWindWithCaiyun = true
				opts.CaiyunToken = token
			}
		}
		exporter := tools.NewExporterWithOptions(opts)
		if err := exporter.ExportRange(context.Background(), *exportStart, *exportEnd); err != nil {
			log.Fatalf("export_range 失败: %v", err)
		}
		log.Println("export_range 完成")
		return
	}

	// 工具：按日期抓取当天0点到当前时间+3小时（两家）
	if *forecastDay != "" {
		if err := tools.RunForecastFetchForDay(context.Background(), *forecastDay); err != nil {
			log.Fatalf("forecast_day 运行失败: %v", err)
		}
		log.Println("forecast_day 完成")
		return
	}

	// 历史数据补完
	if *historicalOnly {
		if *historicalStart == "" || *historicalEnd == "" {
			log.Fatalln("历史数据补完需要提供 --historical_start 与 --historical_end 日期（格式YYYY-MM-DD）")
		}
		if err := forecast.RunOpenMeteoHistoricalFetch(context.Background(), *historicalStart, *historicalEnd); err != nil {
			log.Fatalf("历史数据补完失败: %v", err)
		}
		log.Println("历史数据补完成")
		return
	}

	// Backfill 调试路径
	if *doBackfill {
		if *bfFrom == "" || *bfTo == "" {
			log.Fatalln("backfill 需要提供 --from 与 --to 时间")
		}
		loc, _ := time.LoadLocation("Asia/Shanghai")
		if loc == nil {
			loc = time.FixedZone("CST", 8*3600)
		}
		fromT, err := time.ParseInLocation("2006-01-02 15:04:05", *bfFrom, loc)
		if err != nil {
			log.Fatalf("解析from失败: %v", err)
		}
		toT, err := time.ParseInLocation("2006-01-02 15:04:05", *bfTo, loc)
		if err != nil {
			log.Fatalf("解析to失败: %v", err)
		}
		ctx := context.Background()
		if err := tools.RunBackfill10Min(ctx, tools.BackfillOptions{
			StationID:     *bfStation,
			FromTime:      fromT,
			ToTime:        toT,
			WrapCycleMM:   *bfWrap,
			BucketMinutes: 10,
		}); err != nil {
			log.Fatalf("回填失败: %v", err)
		}
		log.Println("回填完成")
		return
	}

	// 根据命令行参数启动服务
	startExporterBackground := func(wg *sync.WaitGroup) {
		if wg != nil {
			wg.Add(1)
		}
		go func() {
			defer func() {
				if wg != nil {
					wg.Done()
				}
			}()
			log.Println("启动数据导出器（10分钟）...")
			ctx := context.Background()
			// 处理 --wind 覆盖
			var opts tools.ExporterOptions
			if *useWindOverride {
				token := os.Getenv("CAIYUN_TOKEN")
				if token == "" {
					token = config.GetConfig().Forecast.CaiyunToken
				}
				if token == "" {
					log.Println("警告: 指定了 --wind 但未提供彩云 token，忽略风覆盖")
				} else {
					opts.OverrideWindWithCaiyun = true
					opts.CaiyunToken = token
				}
			}
			exporter := tools.NewExporterWithOptions(opts)
			if err := exporter.Start(ctx); err != nil {
				log.Printf("导出器退出: %v", err)
			}
		}()
	}

	startRadarSchedulerBackground := func(wg *sync.WaitGroup) {
		if wg != nil {
			wg.Add(1)
		}
		go func() {
			defer func() {
				if wg != nil {
					wg.Done()
				}
			}()
			log.Println("启动雷达下载任务（每10分钟，无延迟，固定瓦片 7/40/102）...")
			ctx := context.Background()
			_ = radar.Start(ctx, radar.Options{StoreToDB: true, Z: 7, Y: 40, X: 102})
		}()
	}

	startRainSchedulerBackground := func(wg *sync.WaitGroup) {
		if wg != nil {
			wg.Add(1)
		}
		go func() {
			defer func() {
				if wg != nil {
					wg.Done()
				}
			}()
			log.Println("启动一小时降雨下载任务（每10分钟，固定瓦片 7/40/102 与 7/40/104）...")
			ctx := context.Background()
			_ = rain.Start(ctx, rain.Options{StoreToDB: true})
		}()
	}

	if *webOnly {
		// 只启动Web服务器 + 导出器
		startExporterBackground(nil)
		startRadarSchedulerBackground(nil)
		startRainSchedulerBackground(nil)
		log.Println("启动Web服务器模式...")
		if err := server.StartGinServer(); err != nil {
			log.Fatalf("启动Web服务器失败: %v", err)
		}
	} else if *udpOnly {
		// 只启动UDP服务器 + 导出器
		startExporterBackground(nil)
		startRadarSchedulerBackground(nil)
		startRainSchedulerBackground(nil)
		log.Println("启动UDP服务器模式...")
		if err := server.StartUDPServer(); err != nil {
			log.Fatalf("启动UDP服务器失败: %v", err)
		}
	} else {
		// 同时启动UDP和Web服务器 + 导出器
		log.Println("启动完整模式：UDP + Web服务器 + 导出器...")

		var wg sync.WaitGroup
		wg.Add(2)

		// 启动UDP服务器
		go func() {
			defer wg.Done()
			log.Println("正在启动UDP服务器...")
			if err := server.StartUDPServer(); err != nil {
				log.Printf("UDP服务器异常退出: %v", err)
			}
		}()

		// 启动Web服务器
		go func() {
			defer wg.Done()
			log.Println("正在启动Web服务器...")
			if err := server.StartGinServer(); err != nil {
				log.Printf("Web服务器异常退出: %v", err)
			}
		}()

		startExporterBackground(&wg)
		startRadarSchedulerBackground(&wg)
		startRainSchedulerBackground(&wg)
		wg.Wait()
	}
}
