package base

import (
	"strings"
	"time"

	"gorm.io/gorm"

	filemanager "wucher/internal/domain/file_manager"
	"wucher/internal/shared/pkg/uuidv7"
)

const (
	CategoryKeyRegular                      = "regular"
	CategoryKeyHEMS                         = "hems"
	ShiftTimeTypeFixed                      = "FIXED"
	ShiftTimeTypeBMCT                       = "BMCT"
	ShiftTimeTypeECET                       = "ECET"
	BaseContactRoleHEMSEDC          = "hems_edc"
	BaseContactRoleMedPax           = "med_pax"
	BaseContactRoleResponsiblePilot = "responsible_pilot"
)

func NormalizeCategoryType(raw string) (string, bool) {
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "", CategoryKeyRegular, "base":
		return CategoryKeyRegular, true
	case CategoryKeyHEMS, "hems-base", "hems_base":
		return CategoryKeyHEMS, true
	default:
		return "", false
	}
}

type BaseCategory struct {
	ID        []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	Key       string    `gorm:"type:varchar(64);not null;uniqueIndex;column:key"`
	Name      string    `gorm:"type:varchar(150);not null;column:name"`
	CreatedAt time.Time `gorm:"column:created_at"`
	UpdatedAt time.Time `gorm:"column:updated_at"`
}

func (BaseCategory) TableName() string { return "base_categories" }

func (c *BaseCategory) BeforeCreate(tx *gorm.DB) error {
	if len(c.ID) == 0 {
		c.ID = uuidv7.MustBytes()
	}
	return nil
}

type Base struct {
	ID                                 []byte                     `gorm:"type:binary(16);primaryKey;column:id"`
	BaseName                           string                     `gorm:"type:varchar(150);not null;column:base"`
	BaseCategoryID                     []byte                     `gorm:"type:binary(16);index;column:base_category_id"`
	FotoAttachmentID                   []byte                     `gorm:"type:binary(16);index;column:foto_attachment_id"`
	BaseAbbreviation                   string                     `gorm:"type:varchar(64);column:base_abbreviation"`
	Address                            string                     `gorm:"type:varchar(255);column:address"`
	Latitude                           float64                    `gorm:"type:decimal(10,7);not null;default:0;column:latitude"`
	Longitude                          float64                    `gorm:"type:decimal(10,7);not null;default:0;column:longitude"`
	LandlineNumber                     string                     `gorm:"type:varchar(64);column:landline_number"`
	MobileNumber                       string                     `gorm:"type:varchar(64);column:mobile_number"`
	Email                              string                     `gorm:"type:varchar(191);column:email"`
	SortKey                            *int                       `gorm:"column:sortkey"`
	SMSAlert                           bool                       `gorm:"type:tinyint(1);not null;default:0;column:sms_alert"`
	Checklist                          bool                       `gorm:"type:tinyint(1);not null;default:0;column:checklist"`
	LegTime                            string                     `gorm:"type:varchar(64);column:leg_time"`
	DefaultStartTimeType               string                     `gorm:"type:varchar(16);not null;default:'FIXED';column:default_start_time_type"`
	DefaultEndTimeType                 string                     `gorm:"type:varchar(16);not null;default:'FIXED';column:default_end_time_type"`
	DefaultShiftStart                  string                     `gorm:"type:time;column:default_shift_start"`
	DefaultShiftEnd                    string                     `gorm:"type:time;column:default_shift_end"`
	UTC                                string                     `gorm:"type:varchar(100);not null;default:'0';column:utc"`
	Dry                                bool                       `gorm:"type:tinyint(1);not null;default:0;column:dry"`
	ControlCenter                      bool                       `gorm:"type:tinyint(1);not null;default:0;column:control_center"`
	DUL                                bool                       `gorm:"type:tinyint(1);not null;default:0;column:dul"`
	Notes                              string                     `gorm:"type:text;column:notes"`
	IsActive                           bool                       `gorm:"type:tinyint(1);index;not null;default:1;column:is_active"`
	HEMSEDCContactIDs          [][]byte            `gorm:"-:all"`
	MedPaxContactIDs           [][]byte            `gorm:"-:all"`
	ResponsiblePilotContactIDs [][]byte            `gorm:"-:all"`
	HEMSEDCs                   []BaseContactPerson `gorm:"-:all"`
	MedPax                     []BaseContactPerson `gorm:"-:all"`
	ResponsiblePilots          []BaseContactPerson `gorm:"-:all"`
	OperationalShiftTimes              []BaseOperationalShiftTime `gorm:"foreignKey:BaseID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	BaseCategory                       BaseCategory               `gorm:"foreignKey:BaseCategoryID;references:ID"`
	FotoAttachment                     *filemanager.Attachment    `gorm:"foreignKey:FotoAttachmentID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`

	CreatedAt time.Time
	CreatedBy []byte `gorm:"type:binary(16);column:created_by"`
	UpdatedAt time.Time
	UpdatedBy []byte     `gorm:"type:binary(16);column:updated_by"`
	DeletedAt *time.Time `gorm:"column:deleted_at"`
	DeletedBy []byte     `gorm:"type:binary(16);column:deleted_by"`
}

func (Base) TableName() string { return "bases" }

type BaseOperationalShiftTime struct {
	ID            []byte     `gorm:"type:binary(16);primaryKey;column:id"`
	BaseID        []byte     `gorm:"type:binary(16);not null;index:idx_base_operational_shift_times_base_date,priority:1;column:base_id"`
	DateStart     *time.Time `gorm:"type:date;index:idx_base_operational_shift_times_base_date,priority:2;column:date_start"`
	DateEnd       *time.Time `gorm:"type:date;index:idx_base_operational_shift_times_base_date,priority:3;column:date_end"`
	StartTimeType string     `gorm:"type:varchar(16);not null;default:'FIXED';column:start_time_type"`
	EndTimeType   string     `gorm:"type:varchar(16);not null;default:'FIXED';column:end_time_type"`
	ShiftStart    string     `gorm:"type:time;column:shift_start"`
	ShiftEnd      string     `gorm:"type:time;column:shift_end"`

	CreatedAt time.Time  `gorm:"column:created_at"`
	CreatedBy []byte     `gorm:"type:binary(16);column:created_by"`
	UpdatedAt time.Time  `gorm:"column:updated_at"`
	UpdatedBy []byte     `gorm:"type:binary(16);column:updated_by"`
	DeletedAt *time.Time `gorm:"column:deleted_at;index"`
	DeletedBy []byte     `gorm:"type:binary(16);column:deleted_by"`

	Base *Base `gorm:"foreignKey:BaseID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}

func (BaseOperationalShiftTime) TableName() string { return "base_operational_shift_times" }

func (b *BaseOperationalShiftTime) BeforeCreate(tx *gorm.DB) error {
	if len(b.ID) == 0 {
		b.ID = uuidv7.MustBytes()
	}
	return nil
}

type BaseContactRole struct {
	ID        []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	BaseID    []byte    `gorm:"type:binary(16);not null;index;column:base_id"`
	ContactID []byte    `gorm:"type:binary(16);not null;index;column:contact_id"`
	RoleCode  string    `gorm:"type:varchar(64);not null;index;column:role_code"`
	CreatedBy []byte    `gorm:"type:binary(16);column:created_by"`
	UpdatedBy []byte    `gorm:"type:binary(16);column:updated_by"`
	CreatedAt time.Time `gorm:"column:created_at"`
	UpdatedAt time.Time `gorm:"column:updated_at"`
}

type BaseContactPerson struct {
	ContactID []byte
	FirstName string
	LastName  string
}

func (BaseContactRole) TableName() string { return "base_contact_roles" }

func (r *BaseContactRole) BeforeCreate(tx *gorm.DB) error {
	if len(r.ID) == 0 {
		r.ID = uuidv7.MustBytes()
	}
	return nil
}

func (b *Base) BeforeCreate(tx *gorm.DB) error {
	if len(b.ID) == 0 {
		b.ID = uuidv7.MustBytes()
	}
	return nil
}
