package mysql

import (
	"context"
	"errors"
	"strings"

	"gorm.io/gorm"

	flightinspection "wucher/internal/domain/flight_inspection"
	flightinspectionfilechecklist "wucher/internal/domain/flight_inspection_file_checklist"
	helicopterfile "wucher/internal/domain/helicopter_file"
)

type FlightInspectionFileChecklistRepository struct {
	db *gorm.DB
}

func NewFlightInspectionFileChecklistRepository(db *gorm.DB) *FlightInspectionFileChecklistRepository {
	return &FlightInspectionFileChecklistRepository{db: db}
}

func (r *FlightInspectionFileChecklistRepository) Create(ctx context.Context, row *flightinspectionfilechecklist.FlightInspectionFileChecklist) error {
	return r.db.WithContext(ctx).Create(row).Error
}

func (r *FlightInspectionFileChecklistRepository) Update(ctx context.Context, row *flightinspectionfilechecklist.FlightInspectionFileChecklist) error {
	return r.db.WithContext(ctx).Save(row).Error
}

func (r *FlightInspectionFileChecklistRepository) Delete(ctx context.Context, id []byte) error {
	if err := ensureNoReferenceBeforeDelete(ctx, r.db, "flight_inspection_file_checklists", id); err != nil {
		return err
	}
	return mapDeleteConstraintError(r.db.WithContext(ctx).Delete(&flightinspectionfilechecklist.FlightInspectionFileChecklist{}, "id = ?", id).Error)
}

func (r *FlightInspectionFileChecklistRepository) GetByID(ctx context.Context, id []byte) (*flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
	var row flightinspectionfilechecklist.FlightInspectionFileChecklist
	err := r.db.WithContext(ctx).Where("id = ?", id).First(&row).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, nil
	}
	return &row, err
}

func (r *FlightInspectionFileChecklistRepository) List(ctx context.Context, filter string, sort string, limit, offset int) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, int64, error) {
	rows := make([]flightinspectionfilechecklist.FlightInspectionFileChecklist, 0)
	var total int64

	base := r.db.WithContext(ctx).Model(&flightinspectionfilechecklist.FlightInspectionFileChecklist{})
	if strings.TrimSpace(filter) != "" {
		like := "%" + strings.ToLower(strings.TrimSpace(filter)) + "%"
		base = base.Where(
			"LOWER(HEX(id)) LIKE ? OR LOWER(HEX(flight_inspection_id)) LIKE ? OR LOWER(HEX(helicopter_file_id)) LIKE ? OR CAST(is_done AS CHAR) LIKE ?",
			like, like, like, like,
		)
	}

	query := base
	if sort != "" {
		query = query.Order(sort)
	}
	if err := base.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if limit > 0 {
		query = query.Limit(limit).Offset(offset)
	}
	if err := query.Find(&rows).Error; err != nil {
		return nil, 0, err
	}
	return rows, total, nil
}

func (r *FlightInspectionFileChecklistRepository) ListByInspectionID(ctx context.Context, inspectionID []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
	rows := make([]flightinspectionfilechecklist.FlightInspectionFileChecklist, 0)
	if len(inspectionID) != 16 {
		return rows, nil
	}
	err := r.db.WithContext(ctx).
		Where("flight_inspection_id = ?", inspectionID).
		Order("is_done ASC, created_at ASC").
		Find(&rows).Error
	return rows, err
}

func (r *FlightInspectionFileChecklistRepository) FlightInspectionExists(ctx context.Context, inspectionID []byte) (bool, error) {
	if len(inspectionID) != 16 {
		return false, nil
	}
	var total int64
	err := r.db.WithContext(ctx).
		Model(&flightinspection.FlightInspection{}).
		Where("id = ?", inspectionID).
		Count(&total).Error
	return total > 0, err
}

func (r *FlightInspectionFileChecklistRepository) HelicopterFileExists(ctx context.Context, helicopterFileID []byte) (bool, error) {
	if len(helicopterFileID) != 16 {
		return false, nil
	}
	var total int64
	err := r.db.WithContext(ctx).
		Model(&helicopterfile.HelicopterFile{}).
		Where("id = ?", helicopterFileID).
		Count(&total).Error
	return total > 0, err
}
