package database

import (
	"sort"
	"strings"
)

type Attribute struct {
	ID          string `json:"id"`
	Title       string `json:"title"`
	Description string `json:"description"`
	Rating      int    `json:"rating"`
}

type AttributeMap struct {
	Attributes map[string]Attribute `json:"attributes"`
}

func (a *AttributeMap) GetAttribute(key string) Attribute {
	return a.Attributes[key]
}

func (a *AttributeMap) GetAttributesFromList(attr string) []Attribute {
	var attributes []Attribute
	for _, attribute := range strings.Split(attr, ",") {
		attributes = append(attributes, a.GetAttribute(attribute))
	}

	// Sort the attributes slice by Rating from worst to best
	sort.Slice(attributes, func(i, j int) bool {
		return attributes[i].Rating > attributes[j].Rating
	})

	return attributes
}

func (a *AttributeMap) GetSortedAttributes(reverse bool) []Attribute {
	// Return the attributes sorted by Rating from best to worst
	attributes := make([]Attribute, 0, len(a.Attributes))
	for _, attr := range a.Attributes {
		attributes = append(attributes, attr)
	}
	sort.Slice(attributes, func(i, j int) bool {
		if reverse {
			return attributes[i].Rating > attributes[j].Rating
		}
		return attributes[i].Rating < attributes[j].Rating
	})
	return attributes
}

const (
	AttributeRatingInfo    = 0
	AttributeRatingGood    = 1
	AttributeRatingWarning = 2
	AttributeRatingBad     = 3

	AttributeAccountNeeded         = "account-needed"
	AttributeAPIAvailable          = "api"
	AttributeBlockFundsIfFlagged   = "blocks-if-flagged"
	AttributeCustodialWallet       = "custodial-wallet"
	AttributeJavaScriptNeeded      = "needs-js"
	AttributeKYCForSomeFeatures    = "kyc-features"
	AttributeKYCIfObligedByLaw     = "kyc-law"
	AttributeMobileAppAvailable    = "mobile-app"
	AttributeNoCustomerSupport     = "no-customer-support"
	AttributeNoJavaScriptNeeded    = "no-js"
	AttributeNonCustodialWallet    = "non-custodial"
	AttributeNoPersonalInfoNeeded  = "no-personal-info"
	AttributeNoRegistrationNeeded  = "no-registration"
	AttributeOpenSource            = "open-source"
	AttributeP2P                   = "p2p"
	AttributePartnersMayEnforceKYC = "partners-kyc"
	AttributePrivateSourceCode     = "private-code"
	AttributeRefundNoKYC           = "refunds-no-kyc"
	AttributeRefundRequiresKYC     = "refunds-kyc"
	AttributeRiskPreventionSystem  = "risk-prevention-system"
	AttributeSellerWalletCustodial = "seller-wallet-custodial"
	AttributeStrictNoKYCPolicy     = "strict-no-kyc"
	AttributeStrictNoLogPolicy     = "strict-no-log"
	AttributeTelegramBotAvailable  = "telegram-bot"
	AttributeToSNotScrapable       = "tos-not-scrapable"
	AttributeUnclearRefundPolicy   = "unclear-refunds"
)

var ServiceAttributes = AttributeMap{
	Attributes: map[string]Attribute{
		AttributeRiskPreventionSystem: {
			Title:       "Automated Risk-Prevention KYC Enforcement",
			Description: "If the trade is flagged suspicious by the service, the user will be required a KYC procedure in order to get a refund.",
			Rating:      AttributeRatingBad,
			ID:          AttributeRiskPreventionSystem,
		},

		AttributeKYCForSomeFeatures: {
			Title:       "KYC is mandatory to use some features",
			Description: "Some features offered by this service need KYC for the user to use them.",
			Rating:      AttributeRatingBad,
			ID:          AttributeKYCForSomeFeatures,
		},

		AttributeKYCIfObligedByLaw: {
			Title:       "May require KYC/SOF",
			Description: "If obliged to do so by the law or in accordance with the service's internal policy, it may at any time introduce or amend mandatory identification / verification procedures and require the user to complete identification and/or verification and may also require to submit identification documents (KYC) or provide Source of Funds (SOF) information.",
			Rating:      AttributeRatingBad,
			ID:          AttributeKYCIfObligedByLaw,
		},

		AttributeCustodialWallet: {
			Title:       "Custodial wallet",
			Description: "A custodial wallet is a type of crypto wallet where a third party holds and manages the private keys to your wallet and your assets in custody. The custodian is responsible for safeguarding your funds, and you entrust them with your private keys. Custodial wallets are usually provided by centralized crypto exchanges like Coinbase or Binance. Using a custodial wallet requires a great deal of trust in the institution.",
			Rating:      AttributeRatingWarning,
			ID:          AttributeCustodialWallet,
		},

		AttributeAccountNeeded: {
			Title:       "Account needed to use the service",
			Description: "Users require creating and maintaining an account with the service in order to access and use its features. ",
			Rating:      AttributeRatingInfo,
			ID:          AttributeAccountNeeded,
		},

		AttributePrivateSourceCode: {
			Title:       "Source code is private",
			Description: "The source code of the service is not publicly available. This means that the service cannot be audited by the community. This is not necessarily bad, but it is something to keep in mind.",
			Rating:      AttributeRatingInfo,
			ID:          AttributePrivateSourceCode,
		},

		AttributeNoCustomerSupport: {
			Title:       "Poor or no customer support",
			Description: "The service does not offer customer support, or the quality of service provided by the support team is inadequate or unsatisfactory.",
			Rating:      AttributeRatingWarning,
			ID:          AttributeNoCustomerSupport,
		},

		AttributeBlockFundsIfFlagged: {
			Title:       "May block 'suspicious' transactions",
			Description: "User funds may pass through an analysis system that may flag the source of the funds as suspicious. If this happens, the user may be refunded or may be required a KYC procedure.",
			Rating:      AttributeRatingWarning,
			ID:          AttributeBlockFundsIfFlagged,
		},

		AttributeUnclearRefundPolicy: {
			Title:       "Unclear refund policy",
			Description: "This service has an unclear or nonexistent statement about how they manage user refunds.",
			Rating:      AttributeRatingWarning,
			ID:          AttributeUnclearRefundPolicy,
		},

		AttributeSellerWalletCustodial: {
			Title:       "The seller wallet is custodial",
			Description: "The seller wallet is custodial, which means that the seller does not have control over the funds. This is a common practice in P2P exchanges, where the service needs to have control over the funds in order to be able to refund the buyer if the trade enters a dispute.",
			Rating:      AttributeRatingWarning,
			ID:          AttributeSellerWalletCustodial,
		},

		AttributeRefundRequiresKYC: {
			Title:       "Refunds may require KYC or personal information disclosure",
			Description: "In certain cases, the refund process of these services may require the completion of a Know Your Customer (KYC) procedure or the disclosure of personal information. Some services, such as aggregators, usually don't control the KYC procedures of their partners so they fall in this category.",
			Rating:      AttributeRatingWarning,
			ID:          AttributeRefundRequiresKYC,
		},

		AttributeToSNotScrapable: {
			Title:       "ToS page is not possible to scrape",
			Description: "The ToS page has some mechanism that makes it impossible for KYCNOT.me to scrape its content. These methods include, for example, using a canvas and rendering the text on it.",
			Rating:      AttributeRatingWarning,
			ID:          AttributeToSNotScrapable,
		},

		AttributePartnersMayEnforceKYC: {
			Title:       "Partners may enforce KYC policies",
			Description: "The service has partners that may enforce or implement KYC policies. This is common in aggregators, where the service does not control the KYC policies of their partners.",
			Rating:      AttributeRatingWarning,
			ID:          AttributePartnersMayEnforceKYC,
		},

		AttributeNonCustodialWallet: {
			Title:       "Non-custodial wallet",
			Description: "A non-custodial wallet is a type of crypto wallet where the user holds and manages the private keys to the wallet and the assets in custody. The user is responsible for safeguarding their funds, and they are the only ones with access to their private keys. Using a non-custodial wallet requires no trust in any institution.",
			Rating:      AttributeRatingGood,
			ID:          AttributeNonCustodialWallet,
		},

		AttributeOpenSource: {
			Title:       "Open source code",
			Description: "The source code of the service is publicly available. This means that the service can be audited by the community. This is not necessarily good, but it is something to keep in mind.",
			Rating:      AttributeRatingGood,
			ID:          AttributeOpenSource,
		},

		AttributeP2P: {
			Title:       "Peer to peer",
			Description: "Peer-to-peer marketplaces are online platforms where people can trade goods, cryptocurrencies and services directly from each other, without the need for intermediaries like traditional retailers or service providers. In this case, the service is based on such type of market.",
			Rating:      AttributeRatingGood,
			ID:          AttributeP2P,
		},

		AttributeNoRegistrationNeeded: {
			Title:       "No registration needed",
			Description: "Users can access and use the service without creating an account. This enables a faster and more convenient user experience while also offering enhanced privacy and anonymity.",
			Rating:      AttributeRatingGood,
			ID:          AttributeNoRegistrationNeeded,
		},

		AttributeNoPersonalInfoNeeded: {
			Title:       "No personal information needed",
			Description: "Users can create an account with these services without having to provide any personal information such as their name, address, or identification documents. This offers a high degree of privacy and anonymity to users who prefer to keep their personal information private.",
			Rating:      AttributeRatingGood,
			ID:          AttributeNoPersonalInfoNeeded,
		},

		AttributeStrictNoKYCPolicy: {
			Title:       "Strict no-KYC policy",
			Description: "The service has a strict no-KYC policy, which means that it does not require users to complete any KYC procedure in order to access and use its features.",
			Rating:      AttributeRatingGood,
			ID:          AttributeStrictNoKYCPolicy,
		},

		AttributeRefundNoKYC: {
			Title:       "Refunds do not require KYC",
			Description: "The refund process of these services does not require the completion of a Know Your Customer (KYC) procedure or the disclosure of personal information.",
			Rating:      AttributeRatingGood,
			ID:          AttributeRefundNoKYC,
		},

		AttributeStrictNoLogPolicy: {
			Title:       "Strict no-log policy",
			Description: "The service has a strict no-log policy, which means that it does not collect or store any information about its users.",
			Rating:      AttributeRatingGood,
			ID:          AttributeStrictNoLogPolicy,
		},

		AttributeMobileAppAvailable: {
			Title:       "Mobile app available",
			Description: "The service has a mobile app available for download.",
			Rating:      AttributeRatingInfo,
			ID:          AttributeMobileAppAvailable,
		},

		AttributeNoJavaScriptNeeded: {
			Title:       "No JavaScript needed",
			Description: "The service does not require the user to enable JavaScript in order to access and use its features.",
			Rating:      AttributeRatingInfo,
			ID:          AttributeNoJavaScriptNeeded,
		},

		AttributeTelegramBotAvailable: {
			Title:       "Telegram bot available",
			Description: "The service has a Telegram bot available.",
			Rating:      AttributeRatingInfo,
			ID:          AttributeTelegramBotAvailable,
		},

		AttributeAPIAvailable: {
			Title:       "API available",
			Description: "The service has an API available.",
			Rating:      AttributeRatingInfo,
			ID:          AttributeAPIAvailable,
		},

		AttributeJavaScriptNeeded: {
			Title:       "JavaScript needed",
			Description: "The service requires the user to enable JavaScript in order to access and use its features.",
			Rating:      AttributeRatingInfo,
			ID:          AttributeJavaScriptNeeded,
		},
	},
}
