package provider

import (
	"context"
	"regexp"
	"strings"
	"time"

	calent "github.com/tidbcloud/devops/entity/k8scalendar"
)

var trRe = regexp.MustCompile(`(?is)<tr[^>]*>(.*?)</tr>`)
var tdRe = regexp.MustCompile(`(?is)<td[^>]*>(.*?)</td>`)

type gkeProvider struct {
	cfg     Config
	fetcher *httpFetcher
}

func (p *gkeProvider) Cloud() string {
	return calent.CloudGKE
}

func (p *gkeProvider) Fetch(ctx context.Context) ([]*calent.VersionLifecycle, error) {
	html, err := p.fetcher.fetchHTML(ctx, p.cfg.URL)
	if err != nil {
		return nil, err
	}
	return parseGKE(html, p.cfg.URL), nil
}

func parseGKE(html, sourceURL string) []*calent.VersionLifecycle {
	now := time.Now().UTC()
	var out []*calent.VersionLifecycle
	seen := map[string]struct{}{}

	for _, tr := range trRe.FindAllStringSubmatch(html, -1) {
		tds := tdRe.FindAllStringSubmatch(tr[1], -1)
		if len(tds) < 11 {
			continue
		}
		cells := make([]string, len(tds))
		for i, m := range tds {
			cells[i] = stripHTML(m[1])
		}
		version := normalizeVersion(cells[0])
		if version == "" {
			continue
		}
		stableRaw := cleanGkeScheduleCell(cells[5])
		endStdRaw := cleanGkeScheduleCell(cells[9])
		endExtRaw := cleanGkeScheduleCell(cells[10])

		stable, stablePrec := parseGkeScheduleDate(stableRaw)
		endStd, endStdPrec := parseGkeScheduleDate(endStdRaw)
		if stable == nil || endStd == nil {
			continue
		}
		precisions := []string{stablePrec, endStdPrec}
		var endExt *time.Time
		if endExtRaw != "" {
			t, _ := parseGkeScheduleDate(endExtRaw)
			if t != nil {
				endExt = t
			}
		}
		releasePrecision := coarsestGkePrecision(precisions...)

		key := calent.CloudGKE + "-" + version
		if _, ok := seen[key]; ok {
			continue
		}
		seen[key] = struct{}{}
		v := &calent.VersionLifecycle{
			Cloud:                calent.CloudGKE,
			Version:              version,
			CloudProvider:        calent.CloudToProvider(calent.CloudGKE),
			LifecycleStart:       stable.UTC(),
			EndOfStandardSupport: endStd.UTC(),
			ReleasePrecision:     releasePrecision,
			SourceURL:            sourceURL,
			ScrapedAt:            now,
		}
		if endExt != nil {
			t := endExt.UTC()
			v.EndOfExtendedSupport = &t
		}
		v.Fingerprint = v.ComputeFingerprint()
		out = append(out, v)
	}
	return out
}

func stripHTML(s string) string {
	s = regexp.MustCompile(`<[^>]+>`).ReplaceAllString(s, " ")
	s = regexp.MustCompile(`\s+`).ReplaceAllString(s, " ")
	return strings.TrimSpace(s)
}
