package dutyroster

import (
	"time"

	"gorm.io/gorm"

	"wucher/internal/domain/auth"
	"wucher/internal/domain/base"
	"wucher/internal/domain/takeover"
	"wucher/internal/shared/pkg/uuidv7"
)

// DutyRoster stores roster header per base and duty date.
type DutyRoster struct {
	ID         []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	FlightID   []byte    `gorm:"type:binary(16);index:idx_roster_flight_id,unique;column:flight_id"`
	BaseID     []byte    `gorm:"type:binary(16);not null;index:idx_roster_base_date;column:base_id"`
	DutyDate   time.Time `gorm:"type:date;not null;index:idx_roster_base_date;column:duty_date"`

	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"`
	DeletedBy []byte     `gorm:"type:binary(16);column:deleted_by"`

	Base  *base.Base       `gorm:"foreignKey:BaseID;references:ID;-:migration"`
	Crews []DutyRosterCrew `gorm:"foreignKey:RosterID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}

func (DutyRoster) TableName() string { return "duty_rosters" }

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

type DutyRosterCrew struct {
	ID               []byte     `gorm:"type:binary(16);primaryKey;column:id"`
	RosterID         []byte     `gorm:"type:binary(16);not null;index:idx_roster_crew_role;index:idx_roster_crew_unique,unique;column:roster_id"`
	UserID           []byte     `gorm:"type:binary(16);index:idx_roster_crew_unique,unique;column:user_id"`
	TakeoverAcID     []byte     `gorm:"type:binary(16);index;column:takeover_ac_id"`
	RoleCode         string     `gorm:"type:varchar(64);not null;index:idx_roster_crew_role;index:idx_roster_crew_unique,unique;check:chk_roster_crew_role_code,role_code IN ('pilot','doctor','rescuer','helper','other_person','air_rescuer','flight_assistant');column:role_code"`
	CrewType         string     `gorm:"type:varchar(32);not null;default:main;index:idx_roster_crew_unique,unique;check:chk_roster_crew_type,crew_type IN ('main','additional');column:crew_type"`
	NameLabel        string     `gorm:"type:varchar(191);index:idx_roster_crew_unique,unique;column:name_label"`
	MobilePhone      string     `gorm:"type:varchar(64);column:mobile_phone"`
	Email            string     `gorm:"type:varchar(191);column:email"`
	ConfirmAt        *time.Time `gorm:"column:confirm_at"`
	DateStart        *time.Time `gorm:"type:date;index:idx_roster_crew_unique,unique;check:chk_roster_crew_date_range,date_start IS NULL OR date_end IS NULL OR date_start <= date_end;column:date_start"`
	DateEnd          *time.Time `gorm:"type:date;index:idx_roster_crew_unique,unique;column:date_end"`
	ShiftStart       string     `gorm:"type:time;index:idx_roster_crew_unique,unique;column:shift_start"`
	ShiftEnd         string     `gorm:"type:time;index:idx_roster_crew_unique,unique;column:shift_end"`
	FlightInstructor bool       `gorm:"type:tinyint(1);not null;default:0;column:flight_instructor"`
	LineChecker      bool       `gorm:"type:tinyint(1);not null;default:0;column:line_checker"`
	Supervisor       bool       `gorm:"type:tinyint(1);not null;default:0;column:supervisor"`
	Examiner         bool       `gorm:"type:tinyint(1);not null;default:0;column:examiner"`
	CoPilot          bool       `gorm:"type:tinyint(1);not null;default:0;column:co_pilot"`
	
	Roster *DutyRoster `gorm:"foreignKey:RosterID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	User   *auth.User  `gorm:"foreignKey:UserID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
	TakeoverAc *takeover.TakeoverAc `gorm:"foreignKey:TakeoverAcID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`

	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"`
	DeletedBy []byte     `gorm:"type:binary(16);column:deleted_by"`

}

func (DutyRosterCrew) TableName() string { return "duty_roster_crews" }

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

// HeaderView is a denormalized header row for list/get responses.
type HeaderView struct {
	ID                    []byte
	BaseID                []byte
	BaseName              string
	BaseAbbreviation      string
	DefaultShiftStart     string
	DefaultShiftEnd       string
	HelicopterID          []byte
	HelicopterType        string
	HelicopterDesignation string
	HelicopterIdentifier  string
	DutyDate              time.Time
	ShiftStart            string
	ShiftEnd              string
	CreatedAt             time.Time
	CreatedBy             []byte
	UpdatedAt             time.Time
}

// BaseView is a lightweight base projection used in roster listing.
type BaseView struct {
	ID               []byte
	BaseName         string
	BaseAbbreviation string
}

// CrewView is a denormalized crew row for list/get responses.
type CrewView struct {
	ID               []byte
	RosterID         []byte
	UserID           []byte
	Name             string
	Role             string
	RoleCode         string
	CrewType         string
	MobilePhone      string
	Email            string
	DateStart        *time.Time
	DateEnd          *time.Time
	ShiftStart       string
	ShiftEnd         string
	FlightInstructor bool
	LineChecker      bool
	Supervisor       bool
	Examiner         bool
	CoPilot          bool
}

type DeletedCrewResult struct {
	ID        []byte
	RosterID  []byte
	UserID    []byte
	Name      string
	RoleCode  string
	CrewType  string
	DateStart *time.Time
	DateEnd   *time.Time
}
