package service

import (
	"context"
	"fmt"

	"apskel-pos-be/internal/models"
	"apskel-pos-be/internal/processor"

	"mime/multipart"

	"github.com/google/uuid"
)

type FileService interface {
	UploadFile(ctx context.Context, file *multipart.FileHeader, req *models.UploadFileRequest, organizationID, userID uuid.UUID) (*models.FileResponse, error)
	GetFileByID(ctx context.Context, id uuid.UUID) (*models.FileResponse, error)
	UpdateFile(ctx context.Context, id uuid.UUID, req *models.UpdateFileRequest) (*models.FileResponse, error)
	ListFiles(ctx context.Context, req *models.ListFilesRequest) (*models.ListFilesResponse, error)
	GetFileByOrganizationID(ctx context.Context, organizationID uuid.UUID) ([]*models.FileResponse, error)
	GetFileByUserID(ctx context.Context, userID uuid.UUID) ([]*models.FileResponse, error)
}

type FileServiceImpl struct {
	fileProcessor processor.FileProcessor
}

func NewFileServiceImpl(fileProcessor processor.FileProcessor) *FileServiceImpl {
	return &FileServiceImpl{
		fileProcessor: fileProcessor,
	}
}

func (s *FileServiceImpl) UploadFile(ctx context.Context, file *multipart.FileHeader, req *models.UploadFileRequest, organizationID, userID uuid.UUID) (*models.FileResponse, error) {
	if err := s.validateUploadFileRequest(req); err != nil {
		return nil, fmt.Errorf("validation error: %w", err)
	}

	if organizationID == uuid.Nil {
		return nil, fmt.Errorf("organization ID is required")
	}
	if userID == uuid.Nil {
		return nil, fmt.Errorf("user ID is required")
	}

	// Process file upload
	response, err := s.fileProcessor.UploadFile(ctx, file, req, organizationID, userID)
	if err != nil {
		return nil, fmt.Errorf("failed to upload file: %w", err)
	}

	return response, nil
}

func (s *FileServiceImpl) GetFileByID(ctx context.Context, id uuid.UUID) (*models.FileResponse, error) {
	if id == uuid.Nil {
		return nil, fmt.Errorf("invalid file ID")
	}

	response, err := s.fileProcessor.GetFileByID(ctx, id)
	if err != nil {
		return nil, fmt.Errorf("failed to get file: %w", err)
	}

	return response, nil
}

func (s *FileServiceImpl) UpdateFile(ctx context.Context, id uuid.UUID, req *models.UpdateFileRequest) (*models.FileResponse, error) {
	// Validate inputs
	if id == uuid.Nil {
		return nil, fmt.Errorf("invalid file ID")
	}

	// Validate request
	if err := s.validateUpdateFileRequest(req); err != nil {
		return nil, fmt.Errorf("validation error: %w", err)
	}

	// Process file update
	response, err := s.fileProcessor.UpdateFile(ctx, id, req)
	if err != nil {
		return nil, fmt.Errorf("failed to update file: %w", err)
	}

	return response, nil
}

func (s *FileServiceImpl) ListFiles(ctx context.Context, req *models.ListFilesRequest) (*models.ListFilesResponse, error) {
	// Validate request
	if err := s.validateListFilesRequest(req); err != nil {
		return nil, fmt.Errorf("validation error: %w", err)
	}

	// Process file listing
	response, err := s.fileProcessor.ListFiles(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to list files: %w", err)
	}

	return response, nil
}

func (s *FileServiceImpl) GetFileByOrganizationID(ctx context.Context, organizationID uuid.UUID) ([]*models.FileResponse, error) {
	// Validate organization ID
	if organizationID == uuid.Nil {
		return nil, fmt.Errorf("invalid organization ID")
	}

	// Get files by organization
	response, err := s.fileProcessor.GetFileByOrganizationID(ctx, organizationID)
	if err != nil {
		return nil, fmt.Errorf("failed to get files by organization: %w", err)
	}

	return response, nil
}

func (s *FileServiceImpl) GetFileByUserID(ctx context.Context, userID uuid.UUID) ([]*models.FileResponse, error) {
	// Validate user ID
	if userID == uuid.Nil {
		return nil, fmt.Errorf("invalid user ID")
	}

	// Get files by user
	response, err := s.fileProcessor.GetFileByUserID(ctx, userID)
	if err != nil {
		return nil, fmt.Errorf("failed to get files by user: %w", err)
	}

	return response, nil
}

// Validation methods
func (s *FileServiceImpl) validateUploadFileRequest(req *models.UploadFileRequest) error {
	if req == nil {
		return fmt.Errorf("request cannot be nil")
	}

	// File type validation is handled in the processor
	return nil
}

func (s *FileServiceImpl) validateUpdateFileRequest(req *models.UpdateFileRequest) error {
	if req == nil {
		return fmt.Errorf("request cannot be nil")
	}

	// Additional validation can be added here if needed
	return nil
}

func (s *FileServiceImpl) validateListFilesRequest(req *models.ListFilesRequest) error {
	if req == nil {
		return fmt.Errorf("request cannot be nil")
	}

	if req.Page < 1 {
		return fmt.Errorf("page must be greater than 0")
	}

	if req.Limit < 1 || req.Limit > 100 {
		return fmt.Errorf("limit must be between 1 and 100")
	}

	return nil
}
