package transformer

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

	"github.com/google/uuid"
)

// Contract to Model transformers
func UploadFileContractToModel(req *contract.UploadFileRequest) *models.UploadFileRequest {
	if req == nil {
		return nil
	}

	modelReq := &models.UploadFileRequest{
		FileType: constants.FileType(req.FileType),
		IsPublic: req.IsPublic,
		Metadata: req.Metadata,
	}

	return modelReq
}

func UpdateFileContractToModel(req *contract.UpdateFileRequest) *models.UpdateFileRequest {
	if req == nil {
		return nil
	}

	return &models.UpdateFileRequest{
		IsPublic: req.IsPublic,
		Metadata: req.Metadata,
	}
}

func ListFilesQueryToModel(query *contract.ListFilesQuery) *models.ListFilesRequest {
	if query == nil {
		return nil
	}

	req := &models.ListFilesRequest{
		Search: query.Search,
		Page:   query.Page,
		Limit:  query.Limit,
	}

	// Parse UUID fields
	if query.OrganizationID != "" {
		if organizationID, err := uuid.Parse(query.OrganizationID); err == nil {
			req.OrganizationID = &organizationID
		}
	}

	if query.UserID != "" {
		if userID, err := uuid.Parse(query.UserID); err == nil {
			req.UserID = &userID
		}
	}

	// Parse string fields
	if query.FileType != "" {
		fileType := constants.FileType(query.FileType)
		req.FileType = &fileType
	}

	if query.IsPublic != "" {
		if isPublic, err := strconv.ParseBool(query.IsPublic); err == nil {
			req.IsPublic = &isPublic
		}
	}

	// Parse date fields
	if query.DateFrom != "" {
		if dateFrom, err := time.Parse("2006-01-02", query.DateFrom); err == nil {
			req.DateFrom = &dateFrom
		}
	}

	if query.DateTo != "" {
		if dateTo, err := time.Parse("2006-01-02", query.DateTo); err == nil {
			req.DateTo = &dateTo
		}
	}

	return req
}

// Model to Contract transformers
func FileModelToContract(resp *models.FileResponse) *contract.FileResponse {
	if resp == nil {
		return nil
	}

	return &contract.FileResponse{
		ID:             resp.ID,
		OrganizationID: resp.OrganizationID,
		UserID:         resp.UserID,
		FileName:       resp.FileName,
		OriginalName:   resp.OriginalName,
		FileURL:        resp.FileURL,
		FileSize:       resp.FileSize,
		MimeType:       resp.MimeType,
		FileType:       resp.FileType,
		UploadPath:     resp.UploadPath,
		IsPublic:       resp.IsPublic,
		Metadata:       resp.Metadata,
		CreatedAt:      resp.CreatedAt,
		UpdatedAt:      resp.UpdatedAt,
	}
}

func ListFilesModelToContract(resp *models.ListFilesResponse) *contract.ListFilesResponse {
	if resp == nil {
		return nil
	}

	files := make([]*contract.FileResponse, len(resp.Files))
	for i, file := range resp.Files {
		files[i] = FileModelToContract(file)
	}

	return &contract.ListFilesResponse{
		Files:      files,
		TotalCount: resp.TotalCount,
		Page:       resp.Page,
		Limit:      resp.Limit,
		TotalPages: resp.TotalPages,
	}
}

func UploadFileModelToContract(resp *models.UploadFileResponse) *contract.UploadFileResponse {
	if resp == nil {
		return nil
	}

	return &contract.UploadFileResponse{
		File: *FileModelToContract(&resp.File),
	}
}
