package internal

import (
	"database/sql"
	"encoding/json"
	"log"
	"os"

	// "path/filepath"

	"github.com/jobs-scraper/internal/pkg/domain"
	"github.com/jobs-scraper/internal/pkg/infrastructure/rabbitmq"
	"github.com/jobs-scraper/internal/pkg/openai"
	"github.com/jobs-scraper/internal/pkg/openrouter"
	"github.com/jobs-scraper/libs/repo"
)

type JobAnalyzer struct {
	db                    *sql.DB
	jobRepo               *repo.JobRepository
	jobDescriptionRepo    *repo.JobDescriptionRepository
	jobAnalysisResultRepo *repo.JobAnalysisResultRepository
	openRouterService     openrouter.OpenRouterService
	rmq                   *rabbitmq.RabbitMQClient
	openAiService         *openai.OpenAIService
}

func NewJobAnalyzer(db *sql.DB) *JobAnalyzer {
	apiKey := os.Getenv("OPENROUTER_API_KEY")
	model := os.Getenv("CV_AI_MODEL")
	openAiapiKey := os.Getenv("OPENAI_API_KEY")
	if openAiapiKey == "" {
		log.Fatal("OPENAI_API_KEY environment variable is required")
	}

	// Create OpenAI service
	openAiModel := os.Getenv("OPENAI_MODEL")
	if openAiModel == "" {
		openAiModel = "gpt-4o-mini" // Default to cost-effective model
	}

	jobRepo := repo.NewJobRepository(db)
	jobDescriptionRepo := repo.NewJobDescriptionRepository(db)
	jobAnalysisResultRepo := repo.NewJobAnalysisResultRepository(db)
	openRouterService := openrouter.NewOpenRouterService(model, apiKey)
	openAiService := openai.NewOpenAIService(openAiapiKey, openAiModel)

	rmq, err := rabbitmq.NewRabbitMQClient()
	if err != nil {
		log.Printf("Warning: Failed to create RabbitMQ client: %v", err)
	}

	return &JobAnalyzer{
		db:                    db,
		jobRepo:               jobRepo,
		jobDescriptionRepo:    jobDescriptionRepo,
		jobAnalysisResultRepo: jobAnalysisResultRepo,
		openRouterService:     openRouterService,
		rmq:                   rmq,
		openAiService:         openAiService,
	}
}

func (ja *JobAnalyzer) AnalyzeJobs() error {
	// Get jobs that need analysis (status = created)
	jobs, err := ja.jobRepo.GetJobsByStatus(domain.JobStatusCreated)
	if err != nil {
		return err
	}

	log.Printf("Found %d jobs to analyze", len(jobs))

	cv, err := os.ReadFile("cv.txt")

	if err != nil {
		return err
	}

	for _, job := range jobs {
		if err := ja.analyzeJob(job, string(cv)); err != nil {
			log.Printf("Error analyzing job %d: %v", job.ID, err)
			// Update job status to error
			if updateErr := ja.jobRepo.UpdateJobStatus(job.ID, domain.JobStatusError); updateErr != nil {
				log.Printf("Error updating job status to error: %v", updateErr)
			}
			continue
		}

		// Update job status to analyzed
		if err := ja.jobRepo.UpdateJobStatus(job.ID, domain.JobStatusAnalyzed); err != nil {
			log.Printf("Error updating job status to analyzed: %v", err)
		}

		log.Printf("Successfully analyzed job %d", job.ID)
	}

	return nil
}

func (ja *JobAnalyzer) analyzeJob(job domain.Job, cv string) error {
	// Get job description
	jobDescription, jobCriteria, err := ja.jobDescriptionRepo.GetJobDescriptionByJobID(job.ID)
	if err != nil {
		return err
	}

	// Analyze job with CV
	result, err := ja.openAiService.AnalyzeJobDescription(cv, domain.JobDescription{
		JobID:       job.ID,
		Description: jobDescription,
		Criteria:    jobCriteria,
	})

	if err != nil {
		return err
	}

	log.Printf("Analysis result for job %d: Recommendation=%s, Score=%d", job.ID, result.Recommendation, result.ConfidenceScore)

	// Save analysis result to database
	analysisResult := &domain.JobAnalysisResult{
		JobID:           job.ID,
		AnalysisResult:  result.Summary,
		MatchScore:      &result.ConfidenceScore,
		KeySkills:       result.MatchingSkills,
		MissingSkills:   result.MissingSkills,
		Recommendations: &result.Recommendation,
	}

	if err := ja.jobAnalysisResultRepo.SaveAnalysisResult(analysisResult); err != nil {
		log.Printf("Warning: Failed to save analysis result to database: %v", err)
	} else {
		log.Printf("Successfully saved analysis result for job %d to database", job.ID)
	}

	// Publish CV analysis message to RabbitMQ if available
	if ja.rmq != nil {
		message := rabbitmq.CvAnalyzeMessage{
			JobID: job.ID,
		}

		if err := ja.publishCvAnalysisMessage(message); err != nil {
			log.Printf("Warning: Failed to publish CV analysis message: %v", err)
		}
	}

	return nil
}

func (ja *JobAnalyzer) publishCvAnalysisMessage(message rabbitmq.CvAnalyzeMessage) error {
	data, err := json.Marshal(message)
	if err != nil {
		return err
	}

	return ja.rmq.Publish(rabbitmq.CvAnalyzeQueue, rabbitmq.CvAnalyzeExchange, data)
}
