package tender

import (
	"fmt"
	"strconv"
	"strings"
	"time"
	"tm/pkg/mongo"
)

// Tender represents a tender/contract notice entity
type Tender struct {
	mongo.Model               `bson:",inline"`
	ContractNoticeID          string               `bson:"contract_notice_id" json:"contract_notice_id"`
	NoticePublicationID       string               `bson:"notice_publication_id" json:"notice_publication_id"`
	ContractFolderID          string               `bson:"contract_folder_id" json:"contract_folder_id"`
	NoticeTypeCode            string               `bson:"notice_type_code" json:"notice_type_code"`
	NoticeSubTypeCode         string               `bson:"notice_sub_type_code" json:"notice_sub_type_code"`
	NoticeLanguageCode        string               `bson:"notice_language_code" json:"notice_language_code"`
	IssueDate                 int64                `bson:"issue_date" json:"issue_date"`                     // Unix milliseconds
	IssueTime                 int64                `bson:"issue_time" json:"issue_time"`                     // Unix milliseconds
	TenderDeadline            int64                `bson:"tender_deadline" json:"tender_deadline"`           // Unix milliseconds
	PublicationDate           int64                `bson:"publication_date" json:"publication_date"`         // Unix milliseconds
	SubmissionDeadline        int64                `bson:"submission_deadline" json:"submission_deadline"`   // Unix milliseconds
	ApplicationDeadline       int64                `bson:"application_deadline" json:"application_deadline"` // Unix milliseconds
	GazetteID                 string               `bson:"gazette_id" json:"gazette_id"`
	Title                     string               `bson:"title" json:"title"`
	Description               string               `bson:"description" json:"description"`
	ProcurementTypeCode       string               `bson:"procurement_type_code" json:"procurement_type_code"`
	ProcedureCode             string               `bson:"procedure_code" json:"procedure_code"`
	MainClassification        string               `bson:"main_classification" json:"main_classification"`
	AdditionalClassifications []string             `bson:"additional_classifications" json:"additional_classifications"`
	EstimatedValue            float64              `bson:"estimated_value" json:"estimated_value"`
	Currency                  string               `bson:"currency" json:"currency"`
	Duration                  string               `bson:"duration" json:"duration"`
	DurationUnit              string               `bson:"duration_unit" json:"duration_unit"`
	PlaceOfPerformance        string               `bson:"place_of_performance" json:"place_of_performance"`
	CountryCode               string               `bson:"country_code" json:"country_code"`
	RegionCode                string               `bson:"region_code" json:"region_code"`
	CityName                  string               `bson:"city_name" json:"city_name"`
	PostalCode                string               `bson:"postal_code" json:"postal_code"`
	DocumentURI               string               `bson:"document_uri" json:"document_uri"`
	TenderURL                 string               `bson:"tender_url" json:"tender_url"`
	SubmissionURL             string               `bson:"submission_url" json:"submission_url"`
	BuyerOrganization         *Organization        `bson:"buyer_organization" json:"buyer_organization"`
	ReviewOrganization        *Organization        `bson:"review_organization,omitempty" json:"review_organization,omitempty"`
	Organizations             []Organization       `bson:"organizations" json:"organizations"`
	SelectionCriteria         []SelectionCriterion `bson:"selection_criteria" json:"selection_criteria"`
	OfficialLanguages         []string             `bson:"official_languages" json:"official_languages"`
	Status                    TenderStatus         `bson:"status" json:"status"`
	Source                    TenderSource         `bson:"source" json:"source"`
	SourceFileURL             string               `bson:"source_file_url" json:"source_file_url"`
	SourceFileName            string               `bson:"source_file_name" json:"source_file_name"`
	ProcessingMetadata        ProcessingMetadata   `bson:"processing_metadata" json:"processing_metadata"`
	TenderID                  string               `bson:"tender_id" json:"tender_id"` // Implement logic to generate a unique tender_id using the following format: {Source}{BUYER_CODE}{TED_CODE}{DATE}{LOCATION_CODE}

}

// Organization represents organization information
type Organization struct {
	ID               string  `bson:"id" json:"id"`
	Name             string  `bson:"name" json:"name"`
	CompanyID        string  `bson:"company_id,omitempty" json:"company_id,omitempty"`
	WebsiteURI       string  `bson:"website_uri,omitempty" json:"website_uri,omitempty"`
	ContactName      string  `bson:"contact_name,omitempty" json:"contact_name,omitempty"`
	ContactTelephone string  `bson:"contact_telephone,omitempty" json:"contact_telephone,omitempty"`
	ContactEmail     string  `bson:"contact_email,omitempty" json:"contact_email,omitempty"`
	ContactFax       string  `bson:"contact_fax,omitempty" json:"contact_fax,omitempty"`
	Address          Address `bson:"address" json:"address"`
	Role             string  `bson:"role,omitempty" json:"role,omitempty"`
}

// Address represents address information
type Address struct {
	StreetName           string `bson:"street_name,omitempty" json:"street_name,omitempty"`
	CityName             string `bson:"city_name,omitempty" json:"city_name,omitempty"`
	PostalZone           string `bson:"postal_zone,omitempty" json:"postal_zone,omitempty"`
	CountrySubentityCode string `bson:"country_subentity_code,omitempty" json:"country_subentity_code,omitempty"`
	Department           string `bson:"department,omitempty" json:"department,omitempty"`
	Region               string `bson:"region,omitempty" json:"region,omitempty"`
	CountryCode          string `bson:"country_code" json:"country_code"`
}

// SelectionCriterion represents selection criteria
type SelectionCriterion struct {
	TypeCode    string `bson:"type_code" json:"type_code"`
	Description string `bson:"description,omitempty" json:"description,omitempty"`
	LanguageID  string `bson:"language_id,omitempty" json:"language_id,omitempty"`
}

// ProcessingMetadata contains metadata about how the tender was processed
type ProcessingMetadata struct {
	ScrapedAt         int64             `bson:"scraped_at" json:"scraped_at"`     // Unix milliseconds
	ProcessedAt       int64             `bson:"processed_at" json:"processed_at"` // Unix milliseconds
	ProcessingVersion string            `bson:"processing_version" json:"processing_version"`
	ParsingErrors     []string          `bson:"parsing_errors,omitempty" json:"parsing_errors,omitempty"`
	ValidationErrors  []string          `bson:"validation_errors,omitempty" json:"validation_errors,omitempty"`
	EnrichmentData    map[string]string `bson:"enrichment_data,omitempty" json:"enrichment_data,omitempty"`
}

// TenderStatus represents the status of a tender
type TenderStatus string

const (
	TenderStatusActive    TenderStatus = "active"
	TenderStatusExpired   TenderStatus = "expired"
	TenderStatusCancelled TenderStatus = "cancelled"
	TenderStatusAwarded   TenderStatus = "awarded"
	TenderStatusDraft     TenderStatus = "draft"
)

// TenderSource represents the source of tender data
type TenderSource string

const (
	TenderSourceTEDScraper TenderSource = "ted_scraper"
	TenderSourceManual     TenderSource = "manual"
	TenderSourceAPI        TenderSource = "api"
	TenderSourceBulkImport TenderSource = "bulk_import"
)

// TenderSearchCriteria represents search criteria for tenders
type TenderSearchCriteria struct {
	Query               string         `json:"query,omitempty"`
	NoticeType          string         `json:"notice_type,omitempty"`
	ProcurementType     string         `json:"procurement_type,omitempty"`
	CountryCodes        []string       `json:"country_codes,omitempty"`
	RegionCodes         []string       `json:"region_codes,omitempty"`
	Classifications     []string       `json:"classifications,omitempty"`
	MinEstimatedValue   *float64       `json:"min_estimated_value,omitempty"`
	MaxEstimatedValue   *float64       `json:"max_estimated_value,omitempty"`
	Currency            string         `json:"currency,omitempty"`
	DeadlineFrom        *int64         `json:"deadline_from,omitempty"`
	DeadlineTo          *int64         `json:"deadline_to,omitempty"`
	PublicationDateFrom *int64         `json:"publication_date_from,omitempty"`
	PublicationDateTo   *int64         `json:"publication_date_to,omitempty"`
	Status              []TenderStatus `json:"status,omitempty"`
	Source              []TenderSource `json:"source,omitempty"`
	BuyerOrganizationID string         `json:"buyer_organization_id,omitempty"`
	Languages           []string       `json:"languages,omitempty"`
}

// TenderStatistics represents tender statistics
type TenderStatistics struct {
	TotalTenders            int64            `json:"total_tenders"`
	ActiveTenders           int64            `json:"active_tenders"`
	ExpiredTenders          int64            `json:"expired_tenders"`
	TendersByCountry        map[string]int64 `json:"tenders_by_country"`
	TendersByType           map[string]int64 `json:"tenders_by_type"`
	TendersByClassification map[string]int64 `json:"tenders_by_classification"`
	AverageEstimatedValue   float64          `json:"average_estimated_value"`
	TotalEstimatedValue     float64          `json:"total_estimated_value"`
	LastUpdated             int64            `json:"last_updated"` // Unix milliseconds
}

// GetID returns the tender ID
func (t *Tender) GetID() string {
	return t.ID.Hex()
}

// IsActive returns true if the tender is active
func (t *Tender) IsActive() bool {
	return t.Status == TenderStatusActive
}

// IsExpired returns true if the tender deadline has passed
func (t *Tender) IsExpired() bool {
	if t.Status == TenderStatusExpired {
		return true
	}

	if t.TenderDeadline == 0 {
		return false
	}

	// Check if deadline (in milliseconds) is in the past
	now := time.Now().UnixMilli()
	return t.TenderDeadline < now
}

// GetTenderURL returns the TED tender URL
func (t *Tender) GetTenderURL() string {
	if t.TenderURL != "" {
		return t.TenderURL
	}

	if t.NoticePublicationID != "" {
		return generateTenderURL(t.NoticePublicationID)
	}

	return ""
}

// generateTenderURL generates the TED tender URL from NoticePublicationID
func generateTenderURL(noticePublicationID string) string {
	// Remove leading zeros and format for URL
	// Example: 00522942-2025 -> https://ted.europa.eu/en/notice/-/detail/522942-2025
	parts := strings.Split(noticePublicationID, "-")
	if len(parts) != 2 {
		return ""
	}

	// Convert to int and back to string to remove leading zeros
	if num, err := strconv.Atoi(parts[0]); err == nil {
		cleanID := fmt.Sprintf("%d-%s", num, parts[1])
		return fmt.Sprintf("https://ted.europa.eu/en/notice/-/detail/%s", cleanID)
	}

	return ""
}

// GetMainOrganization returns the buyer organization
func (t *Tender) GetMainOrganization() *Organization {
	return t.BuyerOrganization
}

// HasEstimatedValue returns true if the tender has an estimated value
func (t *Tender) HasEstimatedValue() bool {
	return t.EstimatedValue > 0
}

// GetFormattedEstimatedValue returns formatted estimated value with currency
func (t *Tender) GetFormattedEstimatedValue() string {
	if !t.HasEstimatedValue() {
		return ""
	}

	if t.Currency != "" {
		return fmt.Sprintf("%.2f %s", t.EstimatedValue, t.Currency)
	}

	return fmt.Sprintf("%.2f", t.EstimatedValue)
}

// UpdateStatus updates the tender status and updated timestamp
func (t *Tender) UpdateStatus(status TenderStatus) {
	t.Status = status
	t.UpdatedAt = time.Now().UnixMilli()
}

// GetDaysUntilDeadline returns the number of days until the tender deadline
func (t *Tender) GetDaysUntilDeadline() int {
	if t.TenderDeadline == 0 {
		return 0
	}

	now := time.Now().UnixMilli()
	if t.TenderDeadline <= now {
		return 0 // Already expired
	}

	diffMillis := t.TenderDeadline - now
	diffDays := diffMillis / (24 * 60 * 60 * 1000)
	return int(diffDays)
}
