package api

import (
	"encoding/json"
	"net/http"
	"sort"
	"time"

	"party.at/party/cmd/party/parlament"
	"party.at/party/cmd/party/common"
)

type apiPartyStat struct {
	Code    string `json:"code"`
	For     int    `json:"for"`
	Against int    `json:"against"`
}

type apiParlDocument struct {
	Date         string   `json:"date"`
	Title        string   `json:"title"`
	Number       string   `json:"number"`
	Type         string   `json:"type"`
	Topics       []string `json:"topics"`
	VotesFor     []string `json:"votes_for"`
	VotesAgainst []string `json:"votes_against"`
	RouteID      string   `json:"route_id"`
}

func (api *Api) ListParlVotes(w http.ResponseWriter, r *http.Request) {
	all, _, err := api.App.Parlament.ListDocuments(parlament.DocumentFilter{
		Chamber: []string{"NR"},
		Period:  []string{parlament.CurrentPeriod},
	})
	if err != nil {
		api.ServerErrorResponse(w, r, err)
		return
	}

	docs := make([]apiParlDocument, 0, len(all))
	for _, d := range all {
		docs = append(docs, apiParlDocument{
			Date:         d.Date,
			Title:        d.Title,
			Number:       d.Number,
			Type:         d.Type,
			Topics:       parseStringArray(d.Topics),
			VotesFor:     parseStringArray(d.VotesFor),
			VotesAgainst: parseStringArray(d.VotesAgainst),
			RouteID:      d.RouteID,
		})
	}

	sort.Slice(docs, func(i, j int) bool {
		di, _ := time.Parse("02.01.2006", docs[i].Date)
		dj, _ := time.Parse("02.01.2006", docs[j].Date)
		return di.After(dj)
	})

	forCount := make(map[string]int)
	againstCount := make(map[string]int)
	totalWithVotes := 0
	for _, d := range docs {
		if len(d.VotesFor) == 0 && len(d.VotesAgainst) == 0 {
			continue
		}
		totalWithVotes++
		for _, p := range d.VotesFor {
			forCount[p]++
		}
		for _, p := range d.VotesAgainst {
			againstCount[p]++
		}
	}
	seen := make(map[string]bool)
	for p := range forCount {
		seen[p] = true
	}
	for p := range againstCount {
		seen[p] = true
	}
	partyStats := make([]apiPartyStat, 0, len(seen))
	for code := range seen {
		partyStats = append(partyStats, apiPartyStat{
			Code:    code,
			For:     forCount[code],
			Against: againstCount[code],
		})
	}
	sort.Slice(partyStats, func(i, j int) bool {
		ti := partyStats[i].For + partyStats[i].Against
		tj := partyStats[j].For + partyStats[j].Against
		if ti != tj {
			return ti > tj
		}
		return partyStats[i].Code < partyStats[j].Code
	})

	if err := common.WriteJSON(w, http.StatusOK, common.Envelope{
		"documents":        docs,
		"total":            len(docs),
		"total_with_votes": totalWithVotes,
		"party_stats":      partyStats,
	}, nil); err != nil {
		api.ServerErrorResponse(w, r, err)
	}
}

func parseStringArray(s string) []string {
	if s == "" {
		return nil
	}
	var out []string
	if err := json.Unmarshal([]byte(s), &out); err != nil {
		return nil
	}
	return out
}
