package postgres

import (
	"context"
	"database/sql"
	"errors"
	"time"

	"github.com/rede5/gohorsejobs/backend/internal/core/domain/entity"
)

type CompanyRepository struct {
	db *sql.DB
}

func NewCompanyRepository(db *sql.DB) *CompanyRepository {
	return &CompanyRepository{db: db}
}

func (r *CompanyRepository) Save(ctx context.Context, company *entity.Company) (*entity.Company, error) {
	// companies table uses UUID id, DB generates it
	query := `
		INSERT INTO companies (name, slug, type, document, email, description, verified, active, created_at, updated_at)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
		RETURNING id
	`

	slug := company.Name // TODO: slugify function
	var id string
	err := r.db.QueryRowContext(ctx, query,
		company.Name,
		slug,
		"company",
		company.Document,
		company.Contact, // mapped to email
		"{}",            // description as JSON
		true,            // verified
		company.Status == "ACTIVE",
		company.CreatedAt,
		company.UpdatedAt,
	).Scan(&id)

	if err != nil {
		return nil, err
	}
	company.ID = id
	return company, nil
}

func (r *CompanyRepository) FindByID(ctx context.Context, id string) (*entity.Company, error) {
	query := `SELECT id, name, document, email, 
		CASE WHEN active THEN 'ACTIVE' ELSE 'INACTIVE' END as status, 
		created_at, updated_at 
		FROM companies WHERE id = $1`

	row := r.db.QueryRowContext(ctx, query, id)

	c := &entity.Company{}
	var dbID string
	err := row.Scan(&dbID, &c.Name, &c.Document, &c.Contact, &c.Status, &c.CreatedAt, &c.UpdatedAt)
	if err == sql.ErrNoRows {
		return nil, errors.New("company not found")
	}
	c.ID = dbID
	return c, err
}

func (r *CompanyRepository) Update(ctx context.Context, company *entity.Company) (*entity.Company, error) {
	company.UpdatedAt = time.Now()

	query := `
		UPDATE companies 
		SET name=$1, document=$2, email=$3, active=$4, updated_at=$5
		WHERE id=$6
	`
	_, err := r.db.ExecContext(ctx, query,
		company.Name,
		company.Document,
		company.Contact,
		company.Status == "ACTIVE",
		company.UpdatedAt,
		company.ID,
	)
	return company, err
}

func (r *CompanyRepository) Delete(ctx context.Context, id string) error {
	query := `DELETE FROM companies WHERE id = $1`
	_, err := r.db.ExecContext(ctx, query, id)
	return err
}

func (r *CompanyRepository) FindAll(ctx context.Context) ([]*entity.Company, error) {
	query := `SELECT id, name, document, email, 
		CASE WHEN active THEN 'ACTIVE' ELSE 'INACTIVE' END as status, 
		created_at, updated_at 
		FROM companies`
	rows, err := r.db.QueryContext(ctx, query)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var companies []*entity.Company
	for rows.Next() {
		c := &entity.Company{}
		var dbID string
		if err := rows.Scan(&dbID, &c.Name, &c.Document, &c.Contact, &c.Status, &c.CreatedAt, &c.UpdatedAt); err != nil {
			return nil, err
		}
		c.ID = dbID
		companies = append(companies, c)
	}
	return companies, nil
}
