package pdfrender

import (
	"fmt"

	"github.com/pdfcpu/pdfcpu/pkg/api"
)

// RenderPageWithContinuations renders a template page and all necessary continuation pages
// Returns a slice of PDF bytes, one for each page (main + continuations)
func RenderPageWithContinuations(
	viewModel *CharacterSheetViewModel,
	templateName string,
	startPageNumber int,
	date string,
	loader *TemplateLoader,
	renderer *PDFRenderer,
) ([][]byte, error) {
	var pdfs [][]byte
	templateSet := DefaultA4QuerTemplateSet()
	paginator := NewPaginator(templateSet)

	// Build data map from view model
	dataMap := map[string]interface{}{
		"skills":     viewModel.Skills,
		"weapons":    viewModel.Weapons,
		"spells":     viewModel.Spells,
		"equipment":  viewModel.Equipment,
		"magicItems": viewModel.MagicItems,
	}

	// Use unified pagination for all templates
	distributions, err := paginator.PaginateMultiList(dataMap, templateName)
	if err != nil {
		return nil, fmt.Errorf("failed to paginate: %w", err)
	}

	// If no distributions (empty data), render single empty page
	if len(distributions) == 0 {
		pageData, err := PreparePaginatedPageData(viewModel, templateName, startPageNumber, date)
		if err != nil {
			return nil, err
		}
		html, err := loader.RenderTemplateWithInlinedResources(templateName, pageData)
		if err != nil {
			return nil, err
		}
		pdf, err := renderer.RenderHTMLToPDF(html)
		if err != nil {
			return nil, err
		}
		return [][]byte{pdf}, nil
	}

	// Render each distributed page
	for i, dist := range distributions {
		pageData := &PageData{
			Character:     viewModel.Character,
			Attributes:    viewModel.Attributes,
			DerivedValues: viewModel.DerivedValues,
			GameResults:   viewModel.GameResults,
			Meta: PageMeta{
				Date:       date,
				PageNumber: startPageNumber + i,
			},
		}

		// Populate page data from distribution
		populatePageDataFromDistribution(pageData, dist)

		// Render the page
		html, err := loader.RenderTemplateWithInlinedResources(dist.TemplateName, pageData)
		if err != nil {
			return nil, fmt.Errorf("failed to render %s: %w", dist.TemplateName, err)
		}

		pdf, err := renderer.RenderHTMLToPDF(html)
		if err != nil {
			return nil, fmt.Errorf("failed to generate PDF for %s: %w", dist.TemplateName, err)
		}

		pdfs = append(pdfs, pdf)
	}

	return pdfs, nil
}

// populatePageDataFromDistribution populates PageData from a distribution
// This replaces the hardcoded switch statements for each template type
func populatePageDataFromDistribution(pageData *PageData, dist PageDistribution) {
	// Populate data based on block names in distribution
	for blockName, data := range dist.Data {
		switch blockName {
		// Skills blocks
		case "skills_column1":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsColumn1 = skills
				pageData.Skills = append(pageData.Skills, skills...)
			}
		case "skills_column2":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsColumn2 = skills
				pageData.Skills = append(pageData.Skills, skills...)
			}
		case "skills_column3":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsColumn3 = skills
				pageData.Skills = append(pageData.Skills, skills...)
			}
		case "skills_column4":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsColumn4 = skills
				pageData.Skills = append(pageData.Skills, skills...)
			}
		case "skills_learned":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsLearned = skills
			}
		case "skills_learned_1":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsLearned1 = skills
			}
		case "skills_learned_2":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsLearned2 = skills
			}
		case "skills_unlearned":
			if skills, ok := data.([]SkillViewModel); ok {
				// Add to general Skills list for template compatibility
				pageData.Skills = append(pageData.Skills, skills...)
			}
		case "skills_languages":
			if skills, ok := data.([]SkillViewModel); ok {
				pageData.SkillsLanguage = skills
			}

		// Weapons blocks
		case "weapons_main":
			if weapons, ok := data.([]WeaponViewModel); ok {
				pageData.Weapons = weapons
			}

		// Spells blocks
		case "spells_column1":
			if spells, ok := data.([]SpellViewModel); ok {
				pageData.SpellsLeft = spells
				pageData.Spells = append(pageData.Spells, spells...)
			}
		case "spells_column2":
			if spells, ok := data.([]SpellViewModel); ok {
				pageData.SpellsRight = spells
				pageData.Spells = append(pageData.Spells, spells...)
			}

		// Equipment blocks
		case "equipment_worn":
			if equipment, ok := data.([]EquipmentViewModel); ok {
				pageData.Equipment = append(pageData.Equipment, equipment...)
			}
		case "equipment_carried":
			if equipment, ok := data.([]EquipmentViewModel); ok {
				pageData.Equipment = append(pageData.Equipment, equipment...)
			}

		// Magic items
		case "magic_items":
			if items, ok := data.([]MagicItemViewModel); ok {
				pageData.MagicItems = items
			}
		}
	}
}

// MergePDFs merges multiple PDF byte slices into a single PDF
func MergePDFs(pdfList [][]byte, outputPath string) error {
	if len(pdfList) == 0 {
		return fmt.Errorf("no PDFs to merge")
	}

	if len(pdfList) == 1 {
		// Single PDF, just write it
		return nil
	}

	// Use pdfcpu to merge - this is a placeholder, actual implementation
	// would need to save individual PDFs first, then merge them
	// For now, this function signature is defined for future use
	return api.MergeCreateFile(nil, outputPath, false, nil)
}
