package service

import (
	"context"
	"fmt"

	beforeflightinspection "wucher/internal/domain/before_flight_inspection"
	"wucher/internal/shared/pkg/appctx"
)

type BeforeFlightInspectionService struct {
	repo beforeflightinspection.Repository
}

func NewBeforeFlightInspectionService(repo beforeflightinspection.Repository) *BeforeFlightInspectionService {
	return &BeforeFlightInspectionService{repo: repo}
}

func (s *BeforeFlightInspectionService) Upsert(ctx context.Context, flightInspectionID []byte, req *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error) {
	if len(flightInspectionID) != 16 {
		return nil, &beforeflightinspection.ValidationError{Status: 400, Title: "Invalid flight_inspection_id", Detail: "flight_inspection_id must be a valid UUID"}
	}

	exists, err := s.repo.FlightInspectionExists(ctx, flightInspectionID)
	if err != nil {
		return nil, fmt.Errorf("failed to check flight inspection: %w", err)
	}
	if !exists {
		return nil, &beforeflightinspection.ValidationError{Status: 404, Title: "Flight inspection not found", Detail: "The specified flight inspection does not exist"}
	}

	caps, err := s.repo.GetHelicopterCapabilities(ctx, flightInspectionID)
	if err != nil {
		return nil, fmt.Errorf("failed to get helicopter capabilities: %w", err)
	}

	if err := s.validateRequest(req, caps); err != nil {
		return nil, err
	}

	row := &beforeflightinspection.BeforeFlightInspection{
		FlightInspectionID:        flightInspectionID,
		OilEngineNR1Checked:       req.OilEngineNR1Checked,
		OilEngineNR2Checked:       req.OilEngineNR2Checked,
		HydraulicLHChecked:        req.HydraulicLHChecked,
		HydraulicRHChecked:        req.HydraulicRHChecked,
		OilTransmissionMGBChecked: req.OilTransmissionMGBChecked,
		OilTransmissionIGBChecked: req.OilTransmissionIGBChecked,
		OilTransmissionTGBChecked: req.OilTransmissionTGBChecked,
		FuelAmount:                req.FuelAmount,
		FuelUnit:                  s.normalizeFuelUnit(req.FuelUnit),
		FuelAddedAmount:           req.FuelAddedAmount,
	}

	// Keep update idempotent on unique flight_inspection_id.
	// If a row already exists, update it instead of inserting a new one.
	existing, err := s.repo.GetByFlightInspectionID(ctx, flightInspectionID)
	if err != nil {
		return nil, fmt.Errorf("failed to get before flight inspection: %w", err)
	}
	if existing != nil {
		row.ID = append([]byte(nil), existing.ID...)
		row.CreatedBy = append([]byte(nil), existing.CreatedBy...)
		row.CreatedAt = existing.CreatedAt
	}

	userID := appctx.GetUserID(ctx)
	if userID != nil {
		if existing == nil {
			row.CreatedBy = userID
		}
		row.UpdatedBy = userID
	}

	if err := s.repo.Upsert(ctx, row); err != nil {
		return nil, fmt.Errorf("failed to upsert before flight inspection: %w", err)
	}

	return row, nil
}

func (s *BeforeFlightInspectionService) GetByFlightInspectionID(ctx context.Context, flightInspectionID []byte) (*beforeflightinspection.BeforeFlightInspection, error) {
	if len(flightInspectionID) != 16 {
		return nil, &beforeflightinspection.ValidationError{Status: 400, Title: "Invalid flight_inspection_id", Detail: "flight_inspection_id must be a valid UUID"}
	}

	exists, err := s.repo.FlightInspectionExists(ctx, flightInspectionID)
	if err != nil {
		return nil, fmt.Errorf("failed to check flight inspection: %w", err)
	}
	if !exists {
		return nil, &beforeflightinspection.ValidationError{Status: 404, Title: "Flight inspection not found", Detail: "The specified flight inspection does not exist"}
	}

	row, err := s.repo.GetByFlightInspectionID(ctx, flightInspectionID)
	if err != nil {
		return nil, fmt.Errorf("failed to get before flight inspection: %w", err)
	}

	return row, nil
}

func (s *BeforeFlightInspectionService) validateRequest(req *beforeflightinspection.UpsertRequest, caps *beforeflightinspection.HelicopterCapabilities) error {
	if req.FuelAmount != nil && *req.FuelAmount < 0 {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid fuel_amount", Detail: "fuel_amount cannot be negative"}
	}
	if req.FuelAddedAmount != nil && *req.FuelAddedAmount < 0 {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid fuel_added_amount", Detail: "fuel_added_amount cannot be negative"}
	}

	if req.FuelUnit != nil {
		if _, valid := beforeflightinspection.NormalizeFuelUnit(*req.FuelUnit); !valid {
			return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid fuel_unit", Detail: "fuel_unit must be one of: LT, KG, POUND"}
		}
	}

	// Capability=true means corresponding check must be explicitly true.
	if caps.NR1 && (req.OilEngineNR1Checked == nil || !*req.OilEngineNR1Checked) {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_engine_nr1_checked", Detail: "oil_engine_nr1_checked must be true for this helicopter"}
	}
	if caps.NR2 && (req.OilEngineNR2Checked == nil || !*req.OilEngineNR2Checked) {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_engine_nr2_checked", Detail: "oil_engine_nr2_checked must be true for this helicopter"}
	}
	if caps.LH && (req.HydraulicLHChecked == nil || !*req.HydraulicLHChecked) {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid hydraulic_lh_checked", Detail: "hydraulic_lh_checked must be true for this helicopter"}
	}
	if caps.RH && (req.HydraulicRHChecked == nil || !*req.HydraulicRHChecked) {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid hydraulic_rh_checked", Detail: "hydraulic_rh_checked must be true for this helicopter"}
	}
	if caps.MGB && (req.OilTransmissionMGBChecked == nil || !*req.OilTransmissionMGBChecked) {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_transmission_mgb_checked", Detail: "oil_transmission_mgb_checked must be true for this helicopter"}
	}
	if caps.IGB && (req.OilTransmissionIGBChecked == nil || !*req.OilTransmissionIGBChecked) {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_transmission_igb_checked", Detail: "oil_transmission_igb_checked must be true for this helicopter"}
	}
	if caps.TGB && (req.OilTransmissionTGBChecked == nil || !*req.OilTransmissionTGBChecked) {
		return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_transmission_tgb_checked", Detail: "oil_transmission_tgb_checked must be true for this helicopter"}
	}

	return nil
}

func (s *BeforeFlightInspectionService) normalizeFuelUnit(unit *string) string {
	if unit == nil {
		return ""
	}
	normalized, _ := beforeflightinspection.NormalizeFuelUnit(*unit)
	return normalized
}
