package company

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"strings"

	"tm/pkg/ai_summarizer"
)

var ErrAIRecommendationNotConfigured = errors.New("AI recommendation service is not configured")

// AIRecommendationClient defines the interface for company tender recommendation AI operations.
type AIRecommendationClient interface {
	StartOnboarding(ctx context.Context, reqBody ai_summarizer.OnboardingRequest) (*ai_summarizer.OnboardingResponse, error)
	FetchRecommendations(ctx context.Context, reqBody ai_summarizer.RecommendRequest) ([]ai_summarizer.RecommendedTender, error)
}

type onboardingDocumentPayload struct {
	Filename    string `json:"filename"`
	ContentType string `json:"content_type"`
	Content     string `json:"content"`
}

// StartAIOnboarding sends company profile data to the AI team to start recommendation onboarding.
func (s *companyService) StartAIOnboarding(ctx context.Context, companyID string) (*OnboardingResponse, error) {
	if s.aiRecommendationClient == nil {
		return nil, ErrAIRecommendationNotConfigured
	}
	if strings.TrimSpace(companyID) == "" {
		return nil, errors.New("company ID is required")
	}

	company, err := s.repository.GetByID(ctx, companyID)
	if err != nil {
		s.logger.Error("Failed to load company for AI onboarding", map[string]interface{}{
			"company_id": companyID,
			"error":      err.Error(),
		})
		return nil, errors.New("company not found")
	}

	documents, err := s.buildOnboardingDocuments(company.DocumentFileIDs)
	if err != nil {
		s.logger.Error("Failed to prepare company documents for AI onboarding", map[string]interface{}{
			"company_id": companyID,
			"error":      err.Error(),
		})
		return nil, fmt.Errorf("failed to prepare company documents: %w", err)
	}

	websiteURL := ""
	if company.Website != nil {
		websiteURL = strings.TrimSpace(*company.Website)
	}

	s.logger.Info("Starting AI company onboarding", map[string]interface{}{
		"company_id":       companyID,
		"documents_count":  len(company.DocumentFileIDs),
		"has_website_url":  websiteURL != "",
	})

	result, err := s.aiRecommendationClient.StartOnboarding(ctx, ai_summarizer.OnboardingRequest{
		CompanyID:  companyID,
		Documents:  documents,
		WebsiteURL: websiteURL,
	})
	if err != nil {
		s.logger.Error("AI onboarding request failed", map[string]interface{}{
			"company_id": companyID,
			"error":      err.Error(),
		})
		return nil, fmt.Errorf("failed to start AI onboarding: %w", err)
	}

	return &OnboardingResponse{Status: result.Status}, nil
}

// GetAIRecommendations retrieves ranked tender recommendations from the AI team.
func (s *companyService) GetAIRecommendations(ctx context.Context, companyID string) ([]RecommendedTenderResponse, error) {
	if s.aiRecommendationClient == nil {
		return nil, ErrAIRecommendationNotConfigured
	}
	if strings.TrimSpace(companyID) == "" {
		return nil, errors.New("company ID is required")
	}

	if _, err := s.repository.GetByID(ctx, companyID); err != nil {
		s.logger.Error("Failed to load company for AI recommendations", map[string]interface{}{
			"company_id": companyID,
			"error":      err.Error(),
		})
		return nil, errors.New("company not found")
	}

	s.logger.Info("Fetching AI tender recommendations", map[string]interface{}{
		"company_id": companyID,
	})

	items, err := s.aiRecommendationClient.FetchRecommendations(ctx, ai_summarizer.RecommendRequest{
		CompanyID: companyID,
	})
	if err != nil {
		s.logger.Error("AI recommend request failed", map[string]interface{}{
			"company_id": companyID,
			"error":      err.Error(),
		})
		return nil, fmt.Errorf("failed to fetch AI recommendations: %w", err)
	}

	responses := make([]RecommendedTenderResponse, 0, len(items))
	for _, item := range items {
		responses = append(responses, RecommendedTenderResponse{
			Rank:     item.Rank,
			TenderID: item.TenderID,
			Analysis: item.Analysis,
		})
	}

	return responses, nil
}

func (s *companyService) buildOnboardingDocuments(fileIDs []string) (string, error) {
	if len(fileIDs) == 0 {
		return "[]", nil
	}
	if s.fileStore == nil {
		return "", errors.New("file storage is not configured")
	}

	payloads := make([]onboardingDocumentPayload, 0, len(fileIDs))
	for _, fileID := range fileIDs {
		if strings.TrimSpace(fileID) == "" {
			continue
		}

		reader, info, err := s.fileStore.Download(fileID)
		if err != nil {
			s.logger.Warn("Skipping company document for AI onboarding", map[string]interface{}{
				"file_id": fileID,
				"error":   err.Error(),
			})
			continue
		}

		content, readErr := io.ReadAll(reader)
		closeErr := reader.Close()
		if readErr != nil {
			return "", fmt.Errorf("failed to read document %s: %w", fileID, readErr)
		}
		if closeErr != nil {
			s.logger.Warn("Failed to close company document reader", map[string]interface{}{
				"file_id": fileID,
				"error":   closeErr.Error(),
			})
		}

		filename := fileID
		contentType := "application/octet-stream"
		if info != nil {
			if info.Filename != "" {
				filename = info.Filename
			}
			if info.ContentType != "" {
				contentType = info.ContentType
			}
		}

		payloads = append(payloads, onboardingDocumentPayload{
			Filename:    filename,
			ContentType: contentType,
			Content:     base64.StdEncoding.EncodeToString(content),
		})
	}

	encoded, err := json.Marshal(payloads)
	if err != nil {
		return "", fmt.Errorf("failed to encode company documents: %w", err)
	}

	return string(encoded), nil
}
