package util

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path/filepath"

	"apskel-pos-be/internal/entities"

	"github.com/google/uuid"
)

type DefaultChartOfAccount struct {
	ChartOfAccounts []ChartOfAccountTemplate `json:"chart_of_accounts"`
}

type ChartOfAccountTemplate struct {
	Name               string            `json:"name"`
	Code               string            `json:"code"`
	ChartOfAccountType string            `json:"chart_of_account_type"`
	ParentCode         *string           `json:"parent_code"`
	IsSystem           bool              `json:"is_system"`
	Accounts           []AccountTemplate `json:"accounts"`
}

type AccountTemplate struct {
	Name           string  `json:"name"`
	Number         string  `json:"number"`
	AccountType    string  `json:"account_type"`
	OpeningBalance float64 `json:"opening_balance"`
	Description    *string `json:"description"`
}

func CreateDefaultChartOfAccounts(ctx context.Context,
	chartOfAccountProcessor interface{}, // Use interface{} to avoid import cycle
	accountProcessor interface{}, // Use interface{} to avoid import cycle
	organizationID uuid.UUID,
	outletID *uuid.UUID) error {

	// Load the default chart of accounts template
	template, err := loadDefaultChartOfAccountsTemplate()
	if err != nil {
		return fmt.Errorf("failed to load default chart of accounts template: %w", err)
	}

	// Note: In a real implementation, you would get chart of account types
	// and validate that all required types exist

	// Create chart of accounts and accounts
	chartOfAccountMap := make(map[string]uuid.UUID)

	for _, coaTemplate := range template.ChartOfAccounts {
		// Note: In a real implementation, you would call the processor to create the chart of account
		// For now, we'll just store the mapping
		chartOfAccountMap[coaTemplate.Code] = uuid.New() // This would be the actual ID from creation

		// Create accounts for this chart of account
		for _, accountTemplate := range coaTemplate.Accounts {
			accountReq := &entities.Account{
				OrganizationID:   organizationID,
				OutletID:         outletID,
				ChartOfAccountID: chartOfAccountMap[coaTemplate.Code],
				Name:             accountTemplate.Name,
				Number:           accountTemplate.Number,
				AccountType:      entities.AccountType(accountTemplate.AccountType),
				OpeningBalance:   accountTemplate.OpeningBalance,
				CurrentBalance:   accountTemplate.OpeningBalance,
				Description:      accountTemplate.Description,
				IsActive:         true,
				IsSystem:         coaTemplate.IsSystem,
			}

			// Note: In a real implementation, you would call the processor to create the account
			_ = accountReq
		}
	}

	return nil
}

func loadDefaultChartOfAccountsTemplate() (*DefaultChartOfAccount, error) {
	// Get the path to the template file
	templatePath := filepath.Join("internal", "constants", "default_chart_of_accounts.json")

	// Read the template file
	data, err := ioutil.ReadFile(templatePath)
	if err != nil {
		return nil, fmt.Errorf("failed to read template file: %w", err)
	}

	// Parse the JSON
	var template DefaultChartOfAccount
	if err := json.Unmarshal(data, &template); err != nil {
		return nil, fmt.Errorf("failed to parse template JSON: %w", err)
	}

	return &template, nil
}

func getChartOfAccountTypeMap(ctx context.Context, chartOfAccountProcessor interface{}) (map[string]uuid.UUID, error) {
	// This is a placeholder - in a real implementation, you would call the processor
	// to get all chart of account types and create a map of code -> ID
	return map[string]uuid.UUID{
		"ASSET":     uuid.New(),
		"LIABILITY": uuid.New(),
		"EQUITY":    uuid.New(),
		"REVENUE":   uuid.New(),
		"EXPENSE":   uuid.New(),
	}, nil
}
