package flightdata

import (
	"time"

	"gorm.io/gorm"

	facilitydomain "wucher/internal/domain/facility"
	filemanager "wucher/internal/domain/file_manager"
	hospitaldomain "wucher/internal/domain/hospital"
	icaodomain "wucher/internal/domain/icao"
	missiondomain "wucher/internal/domain/mission"
	userdomain "wucher/internal/domain/user"
	"wucher/internal/shared/pkg/uuidv7"
)

type FlightData struct {
	ID        []byte `gorm:"type:binary(16);primaryKey;column:id"`
	MissionID []byte `gorm:"type:binary(16);index;not null;column:mission_id"`
	CoPilotID []byte `gorm:"type:binary(16);index;column:co_pilot_id"`

	FromICAOID     []byte `gorm:"type:binary(16);index;column:from_icao_id"`
	FromHospitalID []byte `gorm:"type:binary(16);index;column:from_hospital_id"`

	ToICAOID     []byte `gorm:"type:binary(16);index;column:to_icao_id"`
	ToHospitalID []byte `gorm:"type:binary(16);index;column:to_hospital_id"`

	FlightTakeOff        time.Time     `gorm:"column:take_off"`
	FlightLanding        time.Time     `gorm:"column:landing"`
	FlightDuration       time.Duration `gorm:"column:duration"`
	FlightType           string        `gorm:"type:varchar(255);column:flight_type"`
	FlightRED            time.Duration `gorm:"column:red"`
	MaxN1                float64       `gorm:"column:max_n1"`
	MaxN2                float64       `gorm:"column:max_n2"`
	PaxCount             int           `gorm:"column:pax_count"`
	TicketNo             string        `gorm:"type:varchar(255);column:ticket_no"`
	Engine               string        `gorm:"type:varchar(255);column:engine"`
	LandingCount         int           `gorm:"column:landing_count"`
	RotorBrakeCycle      int           `gorm:"column:rotor_brake_cycle"`
	HookReleases         int           `gorm:"column:hook_releases"`
	DeliveryNoteNumber   string        `gorm:"type:varchar(255);column:delivery_note_number"`
	CustomerName         string        `gorm:"type:varchar(255);column:customer_name"`
	FlightPlanDistance   float64       `gorm:"column:flight_plan_distance"`
	FlightPlanTime       time.Duration `gorm:"column:flight_plan_time"`
	FlightPlanTrueCourse float64       `gorm:"column:flight_plan_true_course"`
	FuelBeforeFlight     float64       `gorm:"column:fuel_before_flight"`
	FuelUpload           float64       `gorm:"column:fuel_upload"`
	FuelAfterFlight      float64       `gorm:"column:fuel_after_flight"`
	FuelPlanning         float64       `gorm:"column:fuel_planning"`
	FlightPositioning    bool          `gorm:"type:boolean;not null;default:false;column:flight_position"`
	OtherInformation     string        `gorm:"type:text;column:other_information"`
	Status               string        `gorm:"type:varchar(20);not null;default:on_progress;column:status"`

	Mission      *missiondomain.Mission   `gorm:"foreignKey:MissionID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	TypeOfFlight *TypeOfFlight            `gorm:"foreignKey:FlightDataID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
	CoPilot      *userdomain.User         `gorm:"foreignKey:CoPilotID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	FromICAO     *icaodomain.ICAO         `gorm:"foreignKey:FromICAOID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
	FromHospital *hospitaldomain.Hospital `gorm:"foreignKey:FromHospitalID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
	ToICAO       *icaodomain.ICAO         `gorm:"foreignKey:ToICAOID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
	ToHospital   *hospitaldomain.Hospital `gorm:"foreignKey:ToHospitalID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`

	Attachments []filemanager.Attachment `gorm:"-"`

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

func (FlightData) TableName() string { return "flight_data" }

func (f *FlightData) BeforeCreate(_ *gorm.DB) error {
	if len(f.ID) == 0 {
		f.ID = uuidv7.MustBytes()
	}
	return nil
}

type TypeOfFlight struct {
	ID           []byte        `gorm:"type:binary(16);primaryKey;column:id"`
	FlightDataID []byte        `gorm:"type:binary(16);index;not null;column:flight_data_id"`
	Category     string        `gorm:"type:enum('ZNO', 'ANO', 'ZTZ', 'ZSP');not null;column:category"`
	Quantity     int           `gorm:"not null;column:quantity"`
	DurationTime time.Duration `gorm:"not null;column:duration"`

	FlightData *FlightData `gorm:"foreignKey:FlightDataID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}

type HESLOFlight struct {
	ID                  []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	FlightDataID        []byte    `gorm:"type:binary(16);index;not null;column:flight_data_id"`
	ROT                 int       `gorm:"not null;column:rot"`
	FacilityFuelTruckID []byte    `gorm:"type:binary(16);column:fuel_truck_id"`
	LoggingSlingID      []byte    `gorm:"type:binary(16);column:logging_sling_id"`
	CreatedAt           time.Time `gorm:"column:created_at"`

	FlightData        *FlightData              `gorm:"foreignKey:FlightDataID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	FacilityFuelTruck *facilitydomain.Facility `gorm:"foreignKey:FacilityFuelTruckID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
	LoggingSling      *facilitydomain.Facility `gorm:"foreignKey:LoggingSlingID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
}

func (HESLOFlight) TableName() string { return "heslo_flights" }

type HESLOSling struct {
	ID              []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	FacilitySlingID []byte    `gorm:"type:binary(16);column:facility_sling_id"`
	HESLOFlightID   []byte    `gorm:"type:binary(16);index;not null;column:heslo_flight_id"`
	CreatedAt       time.Time `gorm:"column:created_at"`

	HESLOFlight   *HESLOFlight             `gorm:"foreignKey:HESLOFlightID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	FacilitySling *facilitydomain.Facility `gorm:"foreignKey:FacilitySlingID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
}

func (HESLOSling) TableName() string { return "heslo_slings" }

type LoggingSling struct {
	ID              []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	FlightDataID    []byte    `gorm:"type:binary(16);index;not null;column:flight_data_id"`
	FacilitySlingID []byte    `gorm:"type:binary(16);index;column:facility_sling_id"`
	CreatedAt       time.Time `gorm:"column:created_at"`

	FacilitySling *facilitydomain.Facility `gorm:"foreignKey:FacilitySlingID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
	FlightData    *FlightData              `gorm:"foreignKey:FlightDataID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}

func (LoggingSling) TableName() string { return "logging_slings" }

type HECFlight struct {
	ID           []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	FlightDataID []byte    `gorm:"type:binary(16);index;not null;column:flight_data_id"`
	ROT          int       `gorm:"not null;column:rot"`
	HECCycle     int       `gorm:"not null;column:hec_cycle"`
	EquipmentID  []byte    `gorm:"type:binary(16);column:equipment_id"`
	CreatedAt    time.Time `gorm:"column:created_at"`

	FlightData *FlightData              `gorm:"foreignKey:FlightDataID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	Equipment  *facilitydomain.Facility `gorm:"foreignKey:EquipmentID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
}

func (HECFlight) TableName() string { return "hec_flights" }

type HECSling struct {
	ID           []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	FlightDataID []byte    `gorm:"type:binary(16);index;not null;column:flight_data_id"`
	HECSlingID   []byte    `gorm:"type:binary(16);column:hec_sling_id"`
	CreatedAt    time.Time `gorm:"column:created_at"`

	FlightData *FlightData              `gorm:"foreignKey:FlightDataID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
	HECSling   *facilitydomain.Facility `gorm:"foreignKey:HECSlingID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
}

func (HECSling) TableName() string { return "hec_slings" }

type HECLoads struct {
	ID           []byte    `gorm:"type:binary(16);primaryKey;column:id"`
	FlightDataID []byte    `gorm:"type:binary(16);index;not null;column:flight_data_id"`
	LoadCategory string    `gorm:"type:varchar(20);not null;column:load_category"`
	Quantity     int       `gorm:"not null;column:quantity"`
	CreatedAt    time.Time `gorm:"column:created_at"`

	FlightData *FlightData `gorm:"foreignKey:FlightDataID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}

func (HECLoads) TableName() string { return "hec_loads" }

type SPODetails struct {
	HESLO   SPOHESLODetails
	Logging SPOLoggingDetails
	HEC     SPOHECDetails
}

type SPOHESLODetails struct {
	Flights []SPOHESLOFlight
	Slings  []SPOHESLOSling
}

type SPOHESLOFlight struct {
	ID               []byte
	ROT              int
	FuelTruckID      []byte
	FuelTruckName    string
	LoggingSlingID   []byte
	LoggingSlingName string
}

type SPOHESLOSling struct {
	ID            []byte
	HESLOFlightID []byte
	SlingID       []byte
	SlingName     string
}

type SPOLoggingDetails struct {
	Slings []SPOLoggingSling
}

type SPOLoggingSling struct {
	ID        []byte
	SlingID   []byte
	SlingName string
}

type SPOHECDetails struct {
	Flights []SPOHECFlight
	Slings  []SPOHECSling
	Loads   []SPOHECLoad
}

type SPOHECFlight struct {
	ID            []byte
	ROT           int
	HECCycle      int
	EquipmentID   []byte
	EquipmentName string
}

type SPOHECSling struct {
	ID        []byte
	SlingID   []byte
	SlingName string
}

type SPOHECLoad struct {
	ID           []byte
	LoadCategory string
	Quantity     int
}

// SPO upsert input types (write path)

type SPOUpsertData struct {
	HESLO   *SPOHESLOUpsert
	Logging *SPOLoggingUpsert
	HEC     *SPOHECUpsert
}

type SPOHESLOUpsert struct {
	Flights []SPOHESLOFlightUpsert
}

type SPOHESLOFlightUpsert struct {
	ROT            int
	FuelTruckID    []byte
	LoggingSlingID []byte
	Slings         []SPOHESLOSlingUpsert
}

type SPOHESLOSlingUpsert struct {
	SlingID []byte
}

type SPOLoggingUpsert struct {
	Slings []SPOLoggingSlingUpsert
}

type SPOLoggingSlingUpsert struct {
	SlingID []byte
}

type SPOHECUpsert struct {
	Flights []SPOHECFlightUpsert
	Slings  []SPOHECSlingUpsert
	Loads   []SPOHECLoadUpsert
}

type SPOHECFlightUpsert struct {
	ROT         int
	HECCycle    int
	EquipmentID []byte
}

type SPOHECSlingUpsert struct {
	SlingID []byte
}

type SPOHECLoadUpsert struct {
	LoadCategory string
	Quantity     int
}
