/*
 * SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
 * SPDX-License-Identifier: AGPL-3.0-only
 */

package form

import (
	"context"
	"database/sql/driver"
	"dev.tandem.ws/tandem/camper/pkg/locale"
	"net/http"
	"strconv"

	"dev.tandem.ws/tandem/camper/pkg/database"
)

type Select struct {
	Name     string
	Selected []string
	Options  []*Option
	Error    error
}

func (s *Select) setError(err error) {
	s.Error = err
}

func (s *Select) Value() (driver.Value, error) {
	return s.String(), nil
}

func (s *Select) String() string {
	if s.Selected == nil {
		return ""
	}
	return s.Selected[0]
}

func (s *Select) Int() int {
	i, err := strconv.Atoi(s.String())
	if err != nil {
		panic(err)
	}
	return i
}

func (s *Select) FillValue(r *http.Request) {
	s.Selected = r.Form[s.Name]
}

func (s *Select) FillValueIndex(r *http.Request, idx int) {
	if vs := r.Form[s.Name]; len(vs) > idx {
		s.Selected = []string{vs[idx]}
	} else {
		s.Selected = nil
	}
}

func (s *Select) ValidOptionsSelected() bool {
	if len(s.Selected) == 0 {
		return false
	}
	for _, selected := range s.Selected {
		if !s.isValidOption(selected) {
			return false
		}
	}
	return true
}

func (s *Select) isValidOption(selected string) bool {
	for _, option := range s.Options {
		if option.Value == selected {
			return true
		}
	}
	return false
}

func (s *Select) IsSelected(v string) bool {
	for _, selected := range s.Selected {
		if selected == v {
			return true
		}
	}
	return false
}

type Option struct {
	Value string
	Label string
}

func MustGetOptions(ctx context.Context, conn *database.Conn, sql string, args ...interface{}) []*Option {
	rows, err := conn.Query(ctx, sql, args...)
	if err != nil {
		panic(err)
	}
	defer rows.Close()

	var options []*Option
	for rows.Next() {
		option := &Option{}
		err = rows.Scan(&option.Value, &option.Label)
		if err != nil {
			panic(err)
		}
		options = append(options, option)
	}
	if rows.Err() != nil {
		panic(rows.Err())
	}

	return options
}

func MustGetCountryOptions(ctx context.Context, conn *database.Conn, l *locale.Locale) []*Option {
	return MustGetOptions(ctx, conn, "select country.country_code, coalesce(i18n.name, country.name) as l10n_name from country left join country_i18n as i18n on country.country_code = i18n.country_code and i18n.lang_tag = $1 order by l10n_name", l.Language)
}

func MustGetDocumentTypeOptions(ctx context.Context, conn *database.Conn, l *locale.Locale) []*Option {
	return MustGetOptions(ctx, conn, "select idt.id_document_type_id::text, coalesce(i18n.name, idt.name) as l10n_name from id_document_type as idt left join id_document_type_i18n as i18n on idt.id_document_type_id = i18n.id_document_type_id and i18n.lang_tag = $1 order by l10n_name", l.Language)
}