package handlers

import (
	"net/http"
	"strings"

	"github.com/gofiber/fiber/v2"

	flightprepcheck "wucher/internal/domain/flight_prep_check"
	"wucher/internal/shared/pkg/appctx"
	"wucher/internal/shared/pkg/uuidv7"
	"wucher/internal/transport/http/dto"
)

type FlightPrepCheckHandler struct {
	service flightprepcheck.Service
	repo    flightprepcheck.Repository
}

func NewFlightPrepCheckHandler(service flightprepcheck.Service, repo flightprepcheck.Repository) *FlightPrepCheckHandler {
	return &FlightPrepCheckHandler{service: service, repo: repo}
}

// InitializeChecks creates initial flight prep checks for an inspection.
func (h *FlightPrepCheckHandler) InitializeChecks(c *fiber.Ctx) error {
	flightInspectionID, err := uuidv7.ParseString(strings.TrimSpace(c.Params("flight_inspection_id", "")))
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"errors": []fiber.Map{{"code": 400, "title": "Invalid ID", "detail": "flight_inspection_id must be a valid UUID"}}})
	}
	userID, _ := c.Locals("user_id").([]byte)
	ctx := appctx.WithUserID(c.Context(), userID)
	created, svcErr := h.service.InitializeChecks(ctx, flightInspectionID)
	if svcErr != nil {
		if ve, ok := svcErr.(*flightprepcheck.ValidationError); ok {
			return c.Status(ve.Status).JSON(fiber.Map{"errors": []fiber.Map{{"code": ve.Status, "title": ve.Title, "detail": ve.Detail}}})
		}
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"errors": []fiber.Map{{"code": 500, "title": "Internal Error", "detail": svcErr.Error()}}})
	}
	return c.Status(http.StatusCreated).JSON(fiber.Map{"data": fiber.Map{"created": created}})
}

// ListChecks returns flight prep checks for an inspection.
func (h *FlightPrepCheckHandler) ListChecks(c *fiber.Ctx) error {
	flightInspectionID, err := uuidv7.ParseString(strings.TrimSpace(c.Params("flight_inspection_id", "")))
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"errors": []fiber.Map{{"code": 400, "title": "Invalid ID", "detail": "flight_inspection_id must be a valid UUID"}}})
	}
	userID, _ := c.Locals("user_id").([]byte)
	ctx := appctx.WithUserID(c.Context(), userID)
	row, svcErr := h.service.GetByFlightInspection(ctx, flightInspectionID)
	if svcErr != nil {
		if ve, ok := svcErr.(*flightprepcheck.ValidationError); ok {
			return c.Status(ve.Status).JSON(fiber.Map{"errors": []fiber.Map{{"code": ve.Status, "title": ve.Title, "detail": ve.Detail}}})
		}
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"errors": []fiber.Map{{"code": 500, "title": "Internal Error", "detail": svcErr.Error()}}})
	}
	if row == nil {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{"errors": []fiber.Map{{"code": 404, "title": "Not Found", "detail": "flight prep inspection not found"}}})
	}
	return c.Status(http.StatusOK).JSON(fiber.Map{"data": dto.ToFlightPrepCheckDTO(row)})
}

// UpdateCheck updates a single flight prep check row.
func (h *FlightPrepCheckHandler) UpdateCheck(c *fiber.Ctx) error {
	checkID, err := uuidv7.ParseString(strings.TrimSpace(c.Params("check_id", "")))
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"errors": []fiber.Map{{"code": 400, "title": "Invalid ID", "detail": "check_id must be a valid UUID"}}})
	}

	var req dto.FlightPrepCheckUpsertRequest
	if parseErr := c.BodyParser(&req); parseErr != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"errors": []fiber.Map{{"code": 400, "title": "Invalid Request", "detail": parseErr.Error()}}})
	}

	userID, _ := c.Locals("user_id").([]byte)
	ctx := appctx.WithUserID(c.Context(), userID)
	row, svcErr := h.service.UpdateCheck(ctx, checkID, &flightprepcheck.UpsertRequest{
		NOTAMBriefing:         req.Data.Attributes.NotamBriefing,
		WeatherBriefing:       req.Data.Attributes.WeatherBriefing,
		OperationalFlightPlan: req.Data.Attributes.OperationalFlightPlan,
	})
	if svcErr != nil {
		if ve, ok := svcErr.(*flightprepcheck.ValidationError); ok {
			return c.Status(ve.Status).JSON(fiber.Map{"errors": []fiber.Map{{"code": ve.Status, "title": ve.Title, "detail": ve.Detail}}})
		}
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"errors": []fiber.Map{{"code": 500, "title": "Internal Error", "detail": svcErr.Error()}}})
	}
	return c.Status(http.StatusOK).JSON(fiber.Map{"data": dto.ToFlightPrepCheckDTO(row)})
}

// BulkUpdateChecks updates flight prep checks by inspection id.
func (h *FlightPrepCheckHandler) BulkUpdateChecks(c *fiber.Ctx) error {
	flightInspectionID, err := uuidv7.ParseString(strings.TrimSpace(c.Params("flight_inspection_id", "")))
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"errors": []fiber.Map{{"code": 400, "title": "Invalid ID", "detail": "flight_inspection_id must be a valid UUID"}}})
	}

	var req dto.FlightPrepCheckUpsertRequest
	if parseErr := c.BodyParser(&req); parseErr != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"errors": []fiber.Map{{"code": 400, "title": "Invalid Request", "detail": parseErr.Error()}}})
	}

	userID, _ := c.Locals("user_id").([]byte)
	ctx := appctx.WithUserID(c.Context(), userID)
	row, svcErr := h.service.UpsertByFlightInspection(ctx, flightInspectionID, &flightprepcheck.UpsertRequest{
		NOTAMBriefing:         req.Data.Attributes.NotamBriefing,
		WeatherBriefing:       req.Data.Attributes.WeatherBriefing,
		OperationalFlightPlan: req.Data.Attributes.OperationalFlightPlan,
	})
	if svcErr != nil {
		if ve, ok := svcErr.(*flightprepcheck.ValidationError); ok {
			return c.Status(ve.Status).JSON(fiber.Map{"errors": []fiber.Map{{"code": ve.Status, "title": ve.Title, "detail": ve.Detail}}})
		}
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"errors": []fiber.Map{{"code": 500, "title": "Internal Error", "detail": svcErr.Error()}}})
	}
	return c.Status(http.StatusOK).JSON(fiber.Map{"data": dto.ToFlightPrepCheckDTO(row)})
}
