package models

import (
	"time"

	"github.com/google/uuid"
)

// Website visitor tracking (issue #255, section 13): the snippet a workspace
// installs on its own site, and the page views it reports.

// WebsiteConsentMode says when the snippet may record anything.
type WebsiteConsentMode string

const (
	// WebsiteConsentExplicit records nothing until the page calls
	// warmbly('consent', 'granted'). The default, because the product sells into
	// jurisdictions where device and location data need a prior opt-in.
	WebsiteConsentExplicit WebsiteConsentMode = "explicit"
	// WebsiteConsentImplicit records on load. The workspace asserts its own
	// lawful basis by choosing it.
	WebsiteConsentImplicit WebsiteConsentMode = "implicit"
)

// WebsiteLocationPrecision is how much of the IP-derived location is kept.
type WebsiteLocationPrecision string

const (
	WebsiteLocationNone    WebsiteLocationPrecision = "none"
	WebsiteLocationCountry WebsiteLocationPrecision = "country"
	WebsiteLocationCity    WebsiteLocationPrecision = "city"
)

const (
	WebsiteRetentionMinDays     = 7
	WebsiteRetentionMaxDays     = 365
	WebsiteRetentionDefaultDays = 90
)

// WebsiteTrackingSettings is a workspace's tracking configuration. Created on
// first read with tracking disabled, so every workspace has a site key to show
// but nothing is accepted until someone turns it on.
type WebsiteTrackingSettings struct {
	OrganizationID    uuid.UUID                `json:"organization_id"`
	Enabled           bool                     `json:"enabled"`
	SiteKey           string                   `json:"site_key"`
	ConsentMode       WebsiteConsentMode       `json:"consent_mode"`
	LocationPrecision WebsiteLocationPrecision `json:"location_precision"`
	AllowedHosts      []string                 `json:"allowed_hosts"`
	RetentionDays     int                      `json:"retention_days"`
	UpdatedAt         time.Time                `json:"updated_at"`
	// TrackingHost is the deployment's tracking host (TRACKING_DOMAIN), so the
	// dashboard can render the exact snippet. Empty when the install has none.
	TrackingHost string `json:"tracking_host"`
}

// UpdateWebsiteTrackingSettingsRequest is the PATCH body. Every field is
// optional; absent fields keep their value.
type UpdateWebsiteTrackingSettingsRequest struct {
	Enabled           *bool                     `json:"enabled"`
	ConsentMode       *WebsiteConsentMode       `json:"consent_mode"`
	LocationPrecision *WebsiteLocationPrecision `json:"location_precision"`
	AllowedHosts      *[]string                 `json:"allowed_hosts"`
	RetentionDays     *int                      `json:"retention_days"`
}

// WebsiteHitRequest is what the tracking service forwards to the backend for
// one page view: the snippet's payload plus the request facts only the edge
// saw. Device and location are derived here from UserAgent and IP; nothing
// about them is trusted from the snippet.
type WebsiteHitRequest struct {
	SiteKey    string `json:"site_key"`
	VisitorKey string `json:"visitor_key"`
	SessionKey string `json:"session_key"`
	// Consent is what the snippet believes: "granted" after an explicit
	// opt-in, "implicit" when the snippet runs in implicit mode. The
	// workspace's configured mode decides whether that is enough.
	Consent string `json:"consent"`
	// IdentifyToken is the click ticket the redirect appended to the landing
	// URL. It is the only way a hit reaches a contact.
	IdentifyToken string `json:"identify_token"`

	URL          string `json:"url"`
	Title        string `json:"title"`
	Referrer     string `json:"referrer"`
	Language     string `json:"language"`
	Timezone     string `json:"timezone"`
	ScreenWidth  int    `json:"screen_width"`
	ScreenHeight int    `json:"screen_height"`
	// Landing marks the first view of a session, as judged by the snippet.
	Landing bool `json:"landing"`

	UserAgent  string `json:"user_agent"`
	IP         string `json:"ip"`
	OriginHost string `json:"origin_host"`
}

// WebsiteHitResult tells the tracking service what to answer the browser.
type WebsiteHitResult struct {
	// NewVisitorKey is set when the browser must adopt a fresh visitor id:
	// the ticket named a different contact than the one already tied to
	// this browser, so the record was split rather than merged.
	NewVisitorKey string `json:"new_visitor_key,omitempty"`
}

// WebsitePageHit is one counted page view as stored and as shown in the
// contact timeline.
type WebsitePageHit struct {
	ID             uuid.UUID `json:"id"`
	VisitorID      uuid.UUID `json:"visitor_id"`
	SessionKey     string    `json:"session_key"`
	OccurredAt     time.Time `json:"occurred_at"`
	URL            string    `json:"url"`
	Path           string    `json:"path"`
	Title          string    `json:"title"`
	Referrer       string    `json:"referrer"`
	ReferrerDomain string    `json:"referrer_domain"`
	Landing        bool      `json:"landing"`
	UTMSource      string    `json:"utm_source"`
	UTMMedium      string    `json:"utm_medium"`
	UTMCampaign    string    `json:"utm_campaign"`
	UTMTerm        string    `json:"utm_term"`
	UTMContent     string    `json:"utm_content"`
	DeviceType     string    `json:"device_type"`
	OS             string    `json:"os"`
	Browser        string    `json:"browser"`
	BrowserVersion string    `json:"browser_version"`
	DeviceBrand    string    `json:"device_brand"`
	Language       string    `json:"language"`
	Timezone       string    `json:"timezone"`
	ScreenWidth    int       `json:"screen_width"`
	ScreenHeight   int       `json:"screen_height"`
	CountryCode    string    `json:"country_code"`
	Region         string    `json:"region"`
	City           string    `json:"city"`
}

// WebsiteSite is what the ingest path needs to know about a site key.
type WebsiteSite struct {
	OrganizationID    uuid.UUID
	Enabled           bool
	ConsentMode       WebsiteConsentMode
	LocationPrecision WebsiteLocationPrecision
	AllowedHosts      []string
}

// WebsiteVisitor is one browser the snippet has seen.
type WebsiteVisitor struct {
	ID             uuid.UUID
	OrganizationID uuid.UUID
	VisitorKey     string
	ContactID      *uuid.UUID
	IdentifiedAt   *time.Time
	IdentifiedVia  string
}

// WebsiteTrackingRetentionCutoff is one workspace's prune boundary.
type WebsiteTrackingRetentionCutoff struct {
	OrganizationID uuid.UUID
	Before         time.Time
}
