package transformer

import (
	"apskel-pos-be/internal/contract"
	"apskel-pos-be/internal/models"
	"time"
)

// Contract to Model conversions
func CreatePurchaseOrderRequestToModel(req *contract.CreatePurchaseOrderRequest) (*models.CreatePurchaseOrderRequest, error) {
	items := make([]models.CreatePurchaseOrderItemRequest, len(req.Items))
	for i, item := range req.Items {
		items[i] = models.CreatePurchaseOrderItemRequest{
			IngredientID: item.IngredientID,
			Description:  item.Description,
			Quantity:     item.Quantity,
			UnitID:       item.UnitID,
			Amount:       item.Amount,
		}
	}

	// Parse transaction date
	transactionDate, err := time.Parse("2006-01-02", req.TransactionDate)
	if err != nil {
		return nil, err
	}

	// Parse due date
	dueDate, err := time.Parse("2006-01-02", req.DueDate)
	if err != nil {
		return nil, err
	}

	return &models.CreatePurchaseOrderRequest{
		VendorID:          req.VendorID,
		PONumber:          req.PONumber,
		TransactionDate:   transactionDate,
		DueDate:           dueDate,
		Reference:         req.Reference,
		Status:            req.Status,
		Message:           req.Message,
		Items:             items,
		AttachmentFileIDs: req.AttachmentFileIDs,
	}, nil
}

func UpdatePurchaseOrderRequestToModel(req *contract.UpdatePurchaseOrderRequest) (*models.UpdatePurchaseOrderRequest, error) {
	var items []models.UpdatePurchaseOrderItemRequest
	if req.Items != nil {
		items = make([]models.UpdatePurchaseOrderItemRequest, len(req.Items))
		for i, item := range req.Items {
			items[i] = models.UpdatePurchaseOrderItemRequest{
				ID:           item.ID,
				IngredientID: item.IngredientID,
				Description:  item.Description,
				Quantity:     item.Quantity,
				UnitID:       item.UnitID,
				Amount:       item.Amount,
			}
		}
	}

	// Parse transaction date if provided
	var transactionDate *time.Time
	if req.TransactionDate != nil && *req.TransactionDate != "" {
		parsedDate, err := time.Parse("2006-01-02", *req.TransactionDate)
		if err != nil {
			return nil, err
		}
		transactionDate = &parsedDate
	}

	// Parse due date if provided
	var dueDate *time.Time
	if req.DueDate != nil && *req.DueDate != "" {
		parsedDate, err := time.Parse("2006-01-02", *req.DueDate)
		if err != nil {
			return nil, err
		}
		dueDate = &parsedDate
	}

	return &models.UpdatePurchaseOrderRequest{
		VendorID:          req.VendorID,
		PONumber:          req.PONumber,
		TransactionDate:   transactionDate,
		DueDate:           dueDate,
		Reference:         req.Reference,
		Status:            req.Status,
		Message:           req.Message,
		Items:             items,
		AttachmentFileIDs: req.AttachmentFileIDs,
	}, nil
}

func ListPurchaseOrdersRequestToModel(req *contract.ListPurchaseOrdersRequest) *models.ListPurchaseOrdersRequest {
	return &models.ListPurchaseOrdersRequest{
		Page:      req.Page,
		Limit:     req.Limit,
		Search:    req.Search,
		Status:    req.Status,
		VendorID:  req.VendorID,
		StartDate: req.StartDate,
		EndDate:   req.EndDate,
	}
}

// Model to Contract conversions
func PurchaseOrderModelResponseToResponse(po *models.PurchaseOrderResponse) *contract.PurchaseOrderResponse {
	if po == nil {
		return nil
	}

	response := &contract.PurchaseOrderResponse{
		ID:              po.ID,
		OrganizationID:  po.OrganizationID,
		VendorID:        po.VendorID,
		PONumber:        po.PONumber,
		TransactionDate: po.TransactionDate,
		DueDate:         po.DueDate,
		Reference:       po.Reference,
		Status:          po.Status,
		Message:         po.Message,
		TotalAmount:     po.TotalAmount,
		CreatedAt:       po.CreatedAt,
		UpdatedAt:       po.UpdatedAt,
	}

	// Map vendor if present
	if po.Vendor != nil {
		response.Vendor = &contract.VendorResponse{
			ID:             po.Vendor.ID,
			OrganizationID: po.Vendor.OrganizationID,
			Name:           po.Vendor.Name,
			Email:          po.Vendor.Email,
			PhoneNumber:    po.Vendor.PhoneNumber,
			Address:        po.Vendor.Address,
			ContactPerson:  po.Vendor.ContactPerson,
			TaxNumber:      po.Vendor.TaxNumber,
			PaymentTerms:   po.Vendor.PaymentTerms,
			Notes:          po.Vendor.Notes,
			IsActive:       po.Vendor.IsActive,
			CreatedAt:      po.Vendor.CreatedAt,
			UpdatedAt:      po.Vendor.UpdatedAt,
		}
	}

	// Map items if present
	if po.Items != nil {
		response.Items = make([]contract.PurchaseOrderItemResponse, len(po.Items))
		for i, item := range po.Items {
			response.Items[i] = contract.PurchaseOrderItemResponse{
				ID:              item.ID,
				PurchaseOrderID: item.PurchaseOrderID,
				IngredientID:    item.IngredientID,
				Description:     item.Description,
				Quantity:        item.Quantity,
				UnitID:          item.UnitID,
				Amount:          item.Amount,
				CreatedAt:       item.CreatedAt,
				UpdatedAt:       item.UpdatedAt,
			}

			// Map ingredient if present
			if item.Ingredient != nil {
				response.Items[i].Ingredient = &contract.IngredientResponse{
					ID:   item.Ingredient.ID,
					Name: item.Ingredient.Name,
				}
			}

			// Map unit if present
			if item.Unit != nil {
				response.Items[i].Unit = &contract.UnitResponse{
					ID:   item.Unit.ID,
					Name: item.Unit.Name,
				}
			}
		}
	}

	// Map attachments if present
	if po.Attachments != nil {
		response.Attachments = make([]contract.PurchaseOrderAttachmentResponse, len(po.Attachments))
		for i, attachment := range po.Attachments {
			response.Attachments[i] = contract.PurchaseOrderAttachmentResponse{
				ID:              attachment.ID,
				PurchaseOrderID: attachment.PurchaseOrderID,
				FileID:          attachment.FileID,
				CreatedAt:       attachment.CreatedAt,
			}

			// Map file if present
			if attachment.File != nil {
				response.Attachments[i].File = &contract.FileResponse{
					ID:           attachment.File.ID,
					FileName:     attachment.File.FileName,
					OriginalName: attachment.File.OriginalName,
					FileURL:      attachment.File.FileURL,
					FileSize:     attachment.File.FileSize,
					MimeType:     attachment.File.MimeType,
					FileType:     attachment.File.FileType,
					IsPublic:     attachment.File.IsPublic,
					CreatedAt:    attachment.File.CreatedAt,
					UpdatedAt:    attachment.File.UpdatedAt,
				}
			}
		}
	}

	return response
}

func PurchaseOrderModelResponsesToResponses(pos []models.PurchaseOrderResponse) []contract.PurchaseOrderResponse {
	if pos == nil {
		return nil
	}

	responses := make([]contract.PurchaseOrderResponse, len(pos))
	for i, po := range pos {
		response := PurchaseOrderModelResponseToResponse(&po)
		if response != nil {
			responses[i] = *response
		}
	}
	return responses
}

func ListPurchaseOrdersModelResponseToResponse(resp *models.ListPurchaseOrdersResponse) *contract.ListPurchaseOrdersResponse {
	return &contract.ListPurchaseOrdersResponse{
		PurchaseOrders: PurchaseOrderModelResponsesToResponses(resp.PurchaseOrders),
		TotalCount:     resp.TotalCount,
		Page:           resp.Page,
		Limit:          resp.Limit,
		TotalPages:     resp.TotalPages,
	}
}
