package models

import (
	"context"
	"errors"

	"github.com/timetracker/backend/internal/db"
	"github.com/timetracker/backend/internal/types"
	"gorm.io/gorm"
)

// Company represents a company in the system
type Company struct {
	EntityBase
	Name string `gorm:"column:name"`
}

// TableName specifies the table name for GORM
func (Company) TableName() string {
	return "companies"
}

// CompanyCreate contains the fields for creating a new company
type CompanyCreate struct {
	Name string
}

// CompanyUpdate contains the updatable fields of a company
type CompanyUpdate struct {
	ID   types.ULID `gorm:"-"` // Exclude from updates
	Name *string    `gorm:"column:name"`
}

// GetCompanyByID finds a company by its ID
func GetCompanyByID(ctx context.Context, id types.ULID) (*Company, error) {
	var company Company
	result := db.GetEngine(ctx).Where("id = ?", id).First(&company)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, result.Error
	}
	return &company, nil
}

// GetAllCompanies returns all companies
func GetAllCompanies(ctx context.Context) ([]Company, error) {
	var companies []Company
	result := db.GetEngine(ctx).Find(&companies)
	if result.Error != nil {
		return nil, result.Error
	}
	return companies, nil
}

func GetCustomersByCompanyID(ctx context.Context, companyID int) ([]Customer, error) {
	var customers []Customer
	result := db.GetEngine(ctx).Where("company_id = ?", companyID).Find(&customers)
	if result.Error != nil {
		return nil, result.Error
	}
	return customers, nil
}

// CreateCompany creates a new company
func CreateCompany(ctx context.Context, create CompanyCreate) (*Company, error) {
	company := Company{
		Name: create.Name,
	}

	result := db.GetEngine(ctx).Create(&company)
	if result.Error != nil {
		return nil, result.Error
	}
	return &company, nil
}

// UpdateCompany updates an existing company
func UpdateCompany(ctx context.Context, update CompanyUpdate) (*Company, error) {
	company, err := GetCompanyByID(ctx, update.ID)
	if err != nil {
		return nil, err
	}
	if company == nil {
		return nil, errors.New("company not found")
	}

	// Use generic update function
	if err := UpdateModel(ctx, company, update); err != nil {
		return nil, err
	}

	// Load updated data from the database
	return GetCompanyByID(ctx, update.ID)
}

// DeleteCompany deletes a company by its ID
func DeleteCompany(ctx context.Context, id types.ULID) error {
	result := db.GetEngine(ctx).Delete(&Company{}, id)
	return result.Error
}
