package ai_summarizer

import (
	"strings"
	"time"
)

// SummarizeRequest represents the request payload sent to the AI service
// POST /ai/summarize endpoint for on-demand summarization.
type SummarizeRequest struct {
	ContractFolderID    string   `json:"contract_folder_id"`
	NoticePublicationID string   `json:"notice_publication_id"`
	DocumentURL         string   `json:"document_url,omitempty"`
	Title               string   `json:"title,omitempty"`
	Description         string   `json:"description,omitempty"`
	Country             string   `json:"country,omitempty"`
	EstimatedValue      *float64 `json:"estimated_value,omitempty"`
	Currency            string   `json:"currency,omitempty"`
	SubmissionDeadline  string   `json:"submission_deadline,omitempty"`
	AuthorityName       string   `json:"authority_name,omitempty"`
}

// SummarizeRequestInput collects fields used to build SummarizeRequest.
type SummarizeRequestInput struct {
	ContractFolderID    string
	NoticePublicationID string
	DocumentURL         string
	Title               string
	Description         string
	Country             string
	Currency            string
	SubmissionDeadline  int64 // Unix seconds; omitted from request when zero
	EstimatedValue      float64
	AuthorityName       string
}

// NewSummarizeRequest builds a SummarizeRequest for POST /ai/summarize.
func NewSummarizeRequest(in SummarizeRequestInput) SummarizeRequest {
	req := SummarizeRequest{
		ContractFolderID:    strings.TrimSpace(in.ContractFolderID),
		NoticePublicationID: strings.TrimSpace(in.NoticePublicationID),
		DocumentURL:         strings.TrimSpace(in.DocumentURL),
		Title:               in.Title,
		Description:         in.Description,
		Country:             in.Country,
		Currency:            in.Currency,
		AuthorityName:       strings.TrimSpace(in.AuthorityName),
	}
	if in.EstimatedValue > 0 {
		v := in.EstimatedValue
		req.EstimatedValue = &v
	}
	if in.SubmissionDeadline > 0 {
		req.SubmissionDeadline = time.Unix(in.SubmissionDeadline, 0).UTC().Format(time.RFC3339)
	}
	return req
}

// SummarizeResponse represents the response from the AI summarization API.
type SummarizeResponse struct {
	ContractFolderID    string            `json:"contract_folder_id"`
	NoticePublicationID string            `json:"notice_publication_id"`
	NoticeID            string            `json:"notice_id"` // legacy field name
	Summaries           []DocumentSummary `json:"summaries"`
	OverallSummary      *string           `json:"overall_summary"`
}

// ResolvedNoticePublicationID returns the notice publication ID from the response.
func (r *SummarizeResponse) ResolvedNoticePublicationID() string {
	if r == nil {
		return ""
	}
	if id := strings.TrimSpace(r.NoticePublicationID); id != "" {
		return id
	}
	return strings.TrimSpace(r.NoticeID)
}

// DocumentSummary represents a summary for a single document within the AI response.
type DocumentSummary struct {
	DocumentName string `json:"document_name"`
	DocumentType string `json:"document_type"`
	Summary      string `json:"summary"`
	SummaryModel string `json:"summary_model"`
	Error        string `json:"error"` // empty string when no error
}

// ProcedureDocumentsSummary reports scraped documents stored under one procedure folder in MinIO.
type ProcedureDocumentsSummary struct {
	ContractFolderID string `json:"contract_folder_id"`
	DocumentCount    int    `json:"document_count"`
	LatestModified   int64  `json:"latest_modified"` // Unix seconds
}

// StoredDocument represents a document object stored for a tender in MinIO.
type StoredDocument struct {
	ObjectName   string `json:"-"`
	DocumentName string `json:"document_name"`
	Size         int64  `json:"size"`
	LastModified int64  `json:"last_modified"`
	DocumentType string `json:"document_type,omitempty"`
}

// TranslateRequest represents the request payload sent to the AI service
// POST /ai/translate endpoint.
type TranslateRequest struct {
	ContractFolderID    string `json:"contract_folder_id"`
	NoticePublicationID string `json:"notice_publication_id"`
	Title               string `json:"title"`
	Description         string `json:"description"`
	Language            string `json:"language"`
}

// TranslateResponse represents the translation payload from POST /ai/translate.
type TranslateResponse struct {
	ContractFolderID      string `json:"contract_folder_id"`
	NoticePublicationID   string `json:"notice_publication_id"`
	Language              string `json:"language"`
	TranslatedTitle       string `json:"translated_title"`
	TranslatedDescription string `json:"translated_description"`
}

// PipelineTranslateRequest represents the request payload for POST /pipeline/translate.
type PipelineTranslateRequest struct {
	Languages []string `json:"languages"`
}

// PipelineTranslateResponse represents the response from POST /pipeline/translate.
type PipelineTranslateResponse struct {
	Status    string   `json:"status"`
	Languages []string `json:"languages"`
}

// StoredTranslation is one language entry inside tender.json translations map.
type StoredTranslation struct {
	Title       string `json:"title"`
	Description string `json:"description"`
}

// TranslationStatus tracks which languages the async pipeline has finished.
type TranslationStatus struct {
	Done      []string `json:"done"`
	DoneUpper []string `json:"Done"`
}

func (s TranslationStatus) languagesDone() []string {
	if len(s.Done) > 0 {
		return s.Done
	}
	return s.DoneUpper
}

func languageInDone(done []string, language string) bool {
	lang := strings.ToLower(strings.TrimSpace(language))
	for _, item := range done {
		if strings.ToLower(strings.TrimSpace(item)) == lang {
			return true
		}
	}
	return false
}

// TenderJSON represents the structure of the <notice_id>/tender.json file
// stored in the AI service's MinIO bucket.
type TenderJSON struct {
	// Summary is the current pipeline field for the tender-level summary text.
	Summary                string                       `json:"summary"`
	OverallSummary         *string                      `json:"overall_summary"`
	OverallSummaryCamel    *string                      `json:"overallSummary"`
	SummarizeStatus        SummarizeStatus              `json:"summarize_status"`
	SummarizeStatusCamel   SummarizeStatus              `json:"summarizeStatus"`
	Translations           map[string]StoredTranslation `json:"translations"`
	TranslationStatus      TranslationStatus            `json:"translation_status"`
	TranslationStatusCamel TranslationStatus            `json:"translationStatus"`
}

// summaryText returns the best-effort tender-level summary (may be empty).
func (t *TenderJSON) summaryText() string {
	if t == nil {
		return ""
	}
	for _, candidate := range []*string{t.OverallSummary, t.OverallSummaryCamel} {
		if candidate == nil {
			continue
		}
		if text := strings.TrimSpace(*candidate); text != "" {
			return text
		}
	}
	return strings.TrimSpace(t.Summary)
}

// resolved returns whether summarization is marked done and the summary text
// (may be empty when the pipeline finished without text yet).
func (t *TenderJSON) resolved() (done bool, overall string) {
	if t == nil {
		return false, ""
	}
	done = t.SummarizeStatus.isDone() || t.SummarizeStatusCamel.isDone()
	return done, t.summaryText()
}

// SummarizeStatus represents the summarization status inside tender.json.
type SummarizeStatus struct {
	Done      bool `json:"done"` // true when the pipeline has finished
	DoneUpper bool `json:"Done"` // some writers emit PascalCase
}

func (s SummarizeStatus) isDone() bool {
	return s.Done || s.DoneUpper
}

// translationsDone returns languages marked complete by the translation pipeline.
func (t *TenderJSON) translationsDone() []string {
	done := t.TranslationStatus.languagesDone()
	if len(done) > 0 {
		return done
	}
	return t.TranslationStatusCamel.languagesDone()
}

// translationForLanguage returns stored translation text when the pipeline marked
// the language done and non-empty title exists.
func (t *TenderJSON) translationForLanguage(language string) (StoredTranslation, bool) {
	if t == nil || !languageInDone(t.translationsDone(), language) {
		return StoredTranslation{}, false
	}
	lang := strings.ToLower(strings.TrimSpace(language))
	if t.Translations != nil {
		for key, entry := range t.Translations {
			if strings.ToLower(strings.TrimSpace(key)) != lang {
				continue
			}
			if strings.TrimSpace(entry.Title) == "" {
				continue
			}
			return entry, true
		}
	}
	return StoredTranslation{}, false
}
