package services

import (
	"database/sql"
	"fmt"
	"strings"
	"time"

	"github.com/rede5/gohorsejobs/backend/internal/dto"
	"github.com/rede5/gohorsejobs/backend/internal/models"
)

type JobService struct {
	DB *sql.DB
}

func NewJobService(db *sql.DB) *JobService {
	return &JobService{DB: db}
}

func (s *JobService) CreateJob(req dto.CreateJobRequest) (*models.Job, error) {
	query := `
		INSERT INTO jobs (
			company_id, title, description, salary_min, salary_max, salary_type,
			employment_type, working_hours, location, region_id, city_id,
			requirements, benefits, visa_support, language_level, status, created_at, updated_at
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
		RETURNING id, created_at, updated_at
	`

	job := &models.Job{
		CompanyID:      req.CompanyID,
		Title:          req.Title,
		Description:    req.Description,
		SalaryMin:      req.SalaryMin,
		SalaryMax:      req.SalaryMax,
		SalaryType:     req.SalaryType,
		EmploymentType: req.EmploymentType,
		WorkingHours:   req.WorkingHours,
		Location:       req.Location,
		RegionID:       req.RegionID,
		CityID:         req.CityID,
		Requirements:   req.Requirements,
		Benefits:       req.Benefits,
		VisaSupport:    req.VisaSupport,
		LanguageLevel:  req.LanguageLevel,
		Status:         req.Status,
		CreatedAt:      time.Now(),
		UpdatedAt:      time.Now(),
	}

	err := s.DB.QueryRow(
		query,
		job.CompanyID, job.Title, job.Description, job.SalaryMin, job.SalaryMax, job.SalaryType,
		job.EmploymentType, job.WorkingHours, job.Location, job.RegionID, job.CityID,
		job.Requirements, job.Benefits, job.VisaSupport, job.LanguageLevel, job.Status, job.CreatedAt, job.UpdatedAt,
	).Scan(&job.ID, &job.CreatedAt, &job.UpdatedAt)

	if err != nil {
		return nil, err
	}

	return job, nil
}

func (s *JobService) GetJobs(filter dto.JobFilterQuery) ([]models.Job, int, error) {
	baseQuery := `SELECT id, company_id, title, description, salary_min, salary_max, salary_type, employment_type, location, status, created_at, updated_at FROM jobs WHERE 1=1`
	countQuery := `SELECT COUNT(*) FROM jobs WHERE 1=1`

	var args []interface{}
	argId := 1

	if filter.CompanyID != nil {
		baseQuery += fmt.Sprintf(" AND company_id = $%d", argId)
		countQuery += fmt.Sprintf(" AND company_id = $%d", argId)
		args = append(args, *filter.CompanyID)
		argId++
	}

	// Add more filters as needed...

	// Pagination
	limit := filter.Limit
	if limit == 0 {
		limit = 10
	}
	offset := (filter.Page - 1) * limit
	if offset < 0 {
		offset = 0
	}

	paginationQuery := baseQuery + fmt.Sprintf(" LIMIT $%d OFFSET $%d", argId, argId+1)
	paginationArgs := append(args, limit, offset)

	rows, err := s.DB.Query(paginationQuery, paginationArgs...)
	if err != nil {
		return nil, 0, err
	}
	defer rows.Close()

	var jobs []models.Job
	for rows.Next() {
		var j models.Job
		if err := rows.Scan(&j.ID, &j.CompanyID, &j.Title, &j.Description, &j.SalaryMin, &j.SalaryMax, &j.SalaryType, &j.EmploymentType, &j.Location, &j.Status, &j.CreatedAt, &j.UpdatedAt); err != nil {
			return nil, 0, err
		}
		jobs = append(jobs, j)
	}

	var total int
	err = s.DB.QueryRow(countQuery, args...).Scan(&total)
	if err != nil {
		return nil, 0, err
	}

	return jobs, total, nil
}

func (s *JobService) GetJobByID(id int) (*models.Job, error) {
	var j models.Job
	query := `
		SELECT id, company_id, title, description, salary_min, salary_max, salary_type,
		employment_type, working_hours, location, region_id, city_id,
		requirements, benefits, visa_support, language_level, status, created_at, updated_at
		FROM jobs WHERE id = $1
	`
	err := s.DB.QueryRow(query, id).Scan(
		&j.ID, &j.CompanyID, &j.Title, &j.Description, &j.SalaryMin, &j.SalaryMax, &j.SalaryType,
		&j.EmploymentType, &j.WorkingHours, &j.Location, &j.RegionID, &j.CityID,
		&j.Requirements, &j.Benefits, &j.VisaSupport, &j.LanguageLevel, &j.Status, &j.CreatedAt, &j.UpdatedAt,
	)
	if err != nil {
		return nil, err
	}
	return &j, nil
}

func (s *JobService) UpdateJob(id int, req dto.UpdateJobRequest) (*models.Job, error) {
	var setClauses []string
	var args []interface{}
	argId := 1

	if req.Title != nil {
		setClauses = append(setClauses, fmt.Sprintf("title = $%d", argId))
		args = append(args, *req.Title)
		argId++
	}
	if req.Description != nil {
		setClauses = append(setClauses, fmt.Sprintf("description = $%d", argId))
		args = append(args, *req.Description)
		argId++
	}
	// Add other fields...
	if req.Status != nil {
		setClauses = append(setClauses, fmt.Sprintf("status = $%d", argId))
		args = append(args, *req.Status)
		argId++
	}

	if len(setClauses) == 0 {
		return s.GetJobByID(id)
	}

	setClauses = append(setClauses, "updated_at = NOW()")

	query := fmt.Sprintf("UPDATE jobs SET %s WHERE id = $%d RETURNING id, updated_at", strings.Join(setClauses, ", "), argId)
	args = append(args, id)

	var j models.Job
	err := s.DB.QueryRow(query, args...).Scan(&j.ID, &j.UpdatedAt)
	if err != nil {
		return nil, err
	}

	return s.GetJobByID(id)
}

func (s *JobService) DeleteJob(id int) error {
	_, err := s.DB.Exec("DELETE FROM jobs WHERE id = $1", id)
	return err
}
