package services

import (
	"database/sql"
	"time"

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

type ApplicationService struct {
	DB *sql.DB
}

func NewApplicationService(db *sql.DB) *ApplicationService {
	return &ApplicationService{DB: db}
}

func (s *ApplicationService) CreateApplication(req dto.CreateApplicationRequest) (*models.Application, error) {
	query := `
		INSERT INTO applications (
			job_id, user_id, name, phone, line_id, whatsapp, email,
			message, resume_url, documents, status, created_at, updated_at
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
		RETURNING id, created_at, updated_at
	`

	app := &models.Application{
		JobID:     req.JobID,
		UserID:    req.UserID,
		Name:      req.Name,
		Phone:     req.Phone,
		LineID:    req.LineID,
		WhatsApp:  req.WhatsApp,
		Email:     req.Email,
		Message:   req.Message,
		ResumeURL: req.ResumeURL,
		Documents: req.Documents,
		Status:    "pending",
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	err := s.DB.QueryRow(
		query,
		app.JobID, app.UserID, app.Name, app.Phone, app.LineID, app.WhatsApp, app.Email,
		app.Message, app.ResumeURL, app.Documents, app.Status, app.CreatedAt, app.UpdatedAt,
	).Scan(&app.ID, &app.CreatedAt, &app.UpdatedAt)

	if err != nil {
		return nil, err
	}

	return app, nil
}

func (s *ApplicationService) GetApplications(jobID string) ([]models.Application, error) {
	// Simple get by Job ID
	query := `
		SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email,
		message, resume_url, status, created_at, updated_at
		FROM applications WHERE job_id = $1
	`
	rows, err := s.DB.Query(query, jobID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var apps []models.Application
	for rows.Next() {
		var a models.Application
		if err := rows.Scan(
			&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
			&a.Message, &a.ResumeURL, &a.Status, &a.CreatedAt, &a.UpdatedAt,
		); err != nil {
			return nil, err
		}
		apps = append(apps, a)
	}
	return apps, nil
}

func (s *ApplicationService) GetApplicationByID(id string) (*models.Application, error) {
	var a models.Application
	query := `
		SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email,
		message, resume_url, documents, status, created_at, updated_at
		FROM applications WHERE id = $1
	`
	err := s.DB.QueryRow(query, id).Scan(
		&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
		&a.Message, &a.ResumeURL, &a.Documents, &a.Status, &a.CreatedAt, &a.UpdatedAt,
	)
	if err != nil {
		return nil, err
	}
	return &a, nil
}

func (s *ApplicationService) UpdateApplicationStatus(id string, req dto.UpdateApplicationStatusRequest) (*models.Application, error) {
	query := `
		UPDATE applications SET status = $1, updated_at = NOW()
		WHERE id = $2
		RETURNING updated_at
	`
	var updatedAt time.Time
	err := s.DB.QueryRow(query, req.Status, id).Scan(&updatedAt)
	if err != nil {
		return nil, err
	}

	return s.GetApplicationByID(id)
}

func (s *ApplicationService) GetApplicationsByCompany(companyID string) ([]models.Application, error) {
	query := `
		SELECT a.id, a.job_id, a.user_id, a.name, a.phone, a.line_id, a.whatsapp, a.email,
		a.message, a.resume_url, a.status, a.created_at, a.updated_at
		FROM applications a
		JOIN jobs j ON a.job_id = j.id
		WHERE j.company_id = $1
		ORDER BY a.created_at DESC
	`
	rows, err := s.DB.Query(query, companyID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var apps []models.Application
	for rows.Next() {
		var a models.Application
		if err := rows.Scan(
			&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
			&a.Message, &a.ResumeURL, &a.Status, &a.CreatedAt, &a.UpdatedAt,
		); err != nil {
			return nil, err
		}
		apps = append(apps, a)
	}
	return apps, nil
}

func (s *ApplicationService) GetApplicationsByUser(userID string) ([]models.ApplicationWithDetails, error) {
	query := `
		SELECT 
			a.id, a.job_id, a.user_id, a.name, a.phone, a.line_id, a.whatsapp, a.email,
			a.message, a.resume_url, a.status, a.created_at, a.updated_at,
			j.title, c.name, j.company_id
		FROM applications a
		JOIN jobs j ON a.job_id = j.id
		LEFT JOIN companies c ON j.company_id::text = c.id::text
		WHERE a.user_id = $1
		ORDER BY a.created_at DESC
	`
	rows, err := s.DB.Query(query, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var apps []models.ApplicationWithDetails = []models.ApplicationWithDetails{}
	for rows.Next() {
		var a models.ApplicationWithDetails
		var companyID sql.NullString

		if err := rows.Scan(
			&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
			&a.Message, &a.ResumeURL, &a.Status, &a.CreatedAt, &a.UpdatedAt,
			&a.JobTitle, &a.CompanyName, &companyID,
		); err != nil {
			return nil, err
		}
		if companyID.Valid {
			a.CompanyID = companyID.String
		}
		apps = append(apps, a)
	}
	return apps, nil
}

func (s *ApplicationService) DeleteApplication(id string) error {
	query := `DELETE FROM applications WHERE id = $1`
	_, err := s.DB.Exec(query, id)
	return err
}
